springboot 微信授权网页登录操作流程
作者:Wyangcsdb 发布时间:2022-12-12 08:26:19
标签:springboot,授权,登录
操作流程
假设你已经有自己的域名,因为微信公众号和微信回调都需要域名
先看看官方给的文档
根据官方文档,主要流程如下:
(1)引导用户进入授权页面同意授权,获取code
(2)通过code换取网页授权access_token(与基础支持中的access_token不同)
(3)刷新access_token(如果有需要)
(3)通过网页授权access_token和openid获取用户基本信息
提示:以下是本篇文章正文内容,下面案例可供参考
编写微信授权方法和获取用户信息方法
二、使用步骤
获取微信二维码信息
代码如下(示例):
/**
* 公众号微信登录授权
*/
@RequestMapping("/wxLogin")
public void wxLogin(HttpServletResponse response) throws IOException {
//这个url的域名必须在公众号中进行注册验证,这个地址是成功后的回调地址
String backUrl = "http://7ca0c439f61c.ngrok.io/callback";//使用自己的域名
// 第一步:用户同意授权,获取code
//请求地址 snsapi_base snsapi_userinfo
String url = "https://open.weixin.qq.com/connect/oauth2/authorize" +
"?appid=" + HttpClientUtil.APPID +
"&redirect_uri=" + URLEncoder.encode(backUrl,"utf-8") +
"&response_type=code" +
"&scope=snsapi_userinfo" +
"&state=STATE#wechat_redirect";
logger.info("forward重定向地址{" + url + "}");
//必须重定向,否则不能成功
response.sendRedirect(url);
}
备注:在前端页面直接加载url 就可以出现二维码界面了。直接用的微信的页面,也可以根据自己的爱好进行设计页面
/**
* 公众号微信登录授权回调函数
*/
@RequestMapping("/callback")
public UserLoginRes callback(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
UserLoginRes userLoginRes = new UserLoginRes();
try{
WXUserInfoReq weixinUserInfo = new WXUserInfoReq();
/*start 获取微信用户基本信息*/
String code = req.getParameter("code");
//第二步:通过code换取网页授权access_token
String url = "https://api.weixin.qq.com/sns/oauth2/access_token?"
+ "appid=" + HttpClientUtil.APPID
+ "&secret=" + HttpClientUtil.APPSECRET
+ "&code=" + code
+ "&grant_type=authorization_code";
System.out.println(url);
String result = HttpClientUtil.doGet(url);
JSONObject jsonObject = JSON.parseObject(result);
/*
{ "access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE"
}
*/
String openid = jsonObject.getString("openid");
String access_token = jsonObject.getString("access_token");
//第三步验证access_token是否失效;
String chickUrl = "https://api.weixin.qq.com/sns/auth?access_token="
+ access_token + "&openid=" + openid;
String resultInfo = HttpClientUtil.doGet(chickUrl);
JSONObject chickuserInfo = JSON.parseObject(resultInfo);
System.out.println(chickuserInfo.toString());
if (!"0".equals(chickuserInfo.getString("errcode"))) {
String refreshInfo1 = HttpClientUtil.doGet(chickUrl);
JSONObject refreshInfo = JSON.parseObject(refreshInfo1);
/*
{ "access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE" }
*/
access_token = refreshInfo.getString("access_token");
}
// 第四步:拉取用户信息
String infoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token
+ "&openid=" + openid
+ "&lang=zh_CN";
JSONObject userInfo = JSON.parseObject(HttpClientUtil.doGet(infoUrl));
/*
{ "openid":" OPENID",
"nickname": NICKNAME,
"sex":"1",
"province":"PROVINCE"
"city":"CITY",
"country":"COUNTRY",
"headimgurl": "http://wx.qlogo.cn/mmopen/g3MonUZtNHkdmzicIlibx6iaFqAc56vxLSUfpb6n5WKSYVY0ChQKkiaJSgQ1dZuTOgvLLrhJbERQQ4eMsv84eavHiaiceqxibJxCfHe/46",
"privilege":[ "PRIVILEGE1" "PRIVILEGE2" ],
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}
*/
System.out.println(userInfo.getString("openid") + ":" + userInfo.getString("nickname") +":" + userInfo.getString("sex"));
}catch (Exception e){
e.printStackTrace();
userLoginRes.setResult("NO");
userLoginRes.setRtnErrId("ERROR");
userLoginRes.setRtnErrMsg(e.getMessage());
}
return userLoginRes;
}
使用到的HttpClientUtil工具类
代码如下(示例):
public class HttpClientUtil {
//appid、secret为自己公众号平台的appid和secret
public static final String APPID="xxxxxxx";
public static final String APPSECRET ="xxxxxxx";
public static String doGet(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpclient = HttpClients.createDefault();
String resultString = "";
CloseableHttpResponse response = null;
HttpGet httpGet = null;
try {
// 创建uri
URIBuilder builder = new URIBuilder(url);
if (param != null) {
for (String key : param.keySet()) {
builder.addParameter(key, param.get(key));
}
}
URI uri = builder.build();
// 创建http GET请求
httpGet = new HttpGet(uri);
httpGet.setHeader("Host", "api.weixin.qq.com");
httpGet.setHeader("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko");
httpGet.setHeader("Accept", "text/html, application/xhtml+xml, */*");
httpGet.setHeader("Accept-Encoding", "gzip, deflate, br");
httpGet.setHeader("Connection", "keep-alive");
httpGet.setHeader("Accept-Language", "zh-CN");
httpGet.setHeader("Cache-Control", "no-cache");
// 执行请求
response = httpclient.execute(httpGet);
// 判断返回状态是否为200
if (response.getStatusLine().getStatusCode() == 200) {
resultString = EntityUtils.toString(response.getEntity(), "UTF-8");
}
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if (response != null) {
response.close();
}
httpGet.releaseConnection();
httpclient.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doGet(String url) {
return doGet(url, null);
}
public static String doPost(String url, Map<String, String> param) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建参数列表
if (param != null) {
List<NameValuePair> paramList = new ArrayList<>();
for (String key : param.keySet()) {
paramList.add(new BasicNameValuePair(key, param.get(key)));
}
// 模拟表单
UrlEncodedFormEntity entity = new UrlEncodedFormEntity(paramList);
httpPost.setEntity(entity);
}
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doPost(String url) {
return doPost(url, null);
}
public static String doPostJson(String url, String json) {
// 创建Httpclient对象
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = null;
String resultString = "";
try {
// 创建Http Post请求
HttpPost httpPost = new HttpPost(url);
// 创建请求内容
StringEntity entity = new StringEntity(json, ContentType.APPLICATION_JSON);
httpPost.setEntity(entity);
// 执行http请求
response = httpClient.execute(httpPost);
resultString = EntityUtils.toString(response.getEntity(), "utf-8");
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
response.close();
} catch (IOException e) {
e.printStackTrace();
}
}
return resultString;
}
public static String doGetStr(String httpurl) {
HttpURLConnection connection = null;
InputStream is = null;
BufferedReader br = null;
String result = null;// 返回结果字符串
try {
// 创建远程url连接对象
URL url = new URL(httpurl);
// 通过远程url连接对象打开一个连接,强转成httpURLConnection类
connection = (HttpURLConnection) url.openConnection();
// 设置连接方式:get
connection.setRequestMethod("GET");
// 设置连接主机服务器的超时时间:15000毫秒
connection.setConnectTimeout(15000);
// 设置读取远程返回的数据时间:60000毫秒
connection.setReadTimeout(60000);
//设置请求头
connection.setRequestProperty("Host", "api.weixin.qq.com");
connection.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows NT 6.1; WOW64; Trident/7.0; rv:11.0) like Gecko");
connection.setRequestProperty("Accept", "text/html, application/xhtml+xml, */*");
connection.setRequestProperty("Accept-Encoding", "gzip, deflate, br");
connection.setRequestProperty("Connection", "keep-alive");
connection.setRequestProperty("Accept-Language", "zh-CN");
connection.setRequestProperty("Cache-Control", "no-cache");
// 发送请求
connection.connect();
// 通过connection连接,获取输入流
if (connection.getResponseCode() == 200) {
is = connection.getInputStream();
// 封装输入流is,并指定字符集
br = new BufferedReader(new InputStreamReader(is, "UTF-8"));
// 存放数据
StringBuffer sbf = new StringBuffer();
String temp = null;
while ((temp = br.readLine()) != null) {
sbf.append(temp);
sbf.append("\r\n");
}
result = sbf.toString();
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} finally {
// 关闭资源
if (null != br) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (null != is) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
connection.disconnect();// 关闭远程连接
}
return result;
}
}
最后根据实际业务处理用户登录
//3.根据uuid查询用户是否存在,如果存在直接登录。如果不存在则自动注册,在登录
UserInfoModel userInfoByWechat = iUserDao.getUserInfoByWechat(userInfoStr.get("unionid").toString());
if (userInfoByWechat != null) {
return ReturnMessage.success(0,"获取成功",userInfoByWechat);
}
//4.数据库添加用户信息
String username = userInfoStr.get("nickname").toString();
String unionid = userInfoStr.get("unionid").toString();
UserInfoBean userInfoBean = new UserInfoBean();
userInfoBean.setUuid(unionid);
userInfoBean.setUsername(username);
// 微信登录
userInfoBean.setStatus(2);
iUserDao.insertUser(userInfoBean);
//5.根据uuid查询新注册的用户信息
UserInfoModel userInfoModel= iUserDao.getUserInfoByWechat(unionid);
if (userInfoModel == null) {
return ReturnMessage.fail(400,"用户添加失败,请重新操作");
}
来源:https://blog.csdn.net/Wyangcsdb/article/details/109595772
0
投稿
猜你喜欢
- 一、线程的优先级别线程优先级别的使用范例:package cn.galc.test;public class TestThread6 { p
- 前言相信很多Java开发都遇到过一个面试题:Resource和Autowired的区别是什么?这个问题的答案相信基本都清楚,但是这两者在Sp
- Thymeleaf 是一款用于渲染 XML/XHTML/HTML5 内容的模板引擎。它与 JSP,Velocity,FreeMaker 等模
- 1. 为什么要使用线程池使用线程池通常由以下两个原因:频繁创建销毁线程需要消耗系统资源,使用线程池可以复用线程。使用线程池可以更容易管理线程
- 著名的Java单元测试框架Junit 4已经出来很长时间了,当时我发现JUnit 5已经处于测试版,就准备写文章来介绍JUnit 5.不过因
- 前言dynamic-tp是一个轻量级的动态线程池插件,它是一个基于配置中心的动态线程池,线程池的参数可以通过配置中心配置进行动态的修改,在配
- 目录一、值类型和引用类型的区别1、赋值时的区别2、内存分配的区别3、来自继承结构的区别二、总结一、值类型和引用类型的区别.NET的类型可以分
- 我们开始今天的正文。首先,来看一下今天分享的并发编程最佳学习路线包含哪些内容。最佳学习路线接下来,我们再来依次看下具体要学习哪些知识吧。并发
- 1.@RequestMapping的介绍通过@RequestMapping,我们可以把请求地址和方法进行绑定的,可以在类、方法上进行声明。类
- 本文实例讲述了C#中累加器函数Aggregate用法。分享给大家供大家参考。具体如下:var shouldExclude = false;v
- Kotlin基础教程之Run,标签Label,函数Function-Type在Java中可以使用{}建立一个匿名的代码块,代码块会被正常的执
- 本文实例为大家分享了java读取cvs文件并导入数据库的具体代码,供大家参考,具体内容如下首先获取文件夹下面的所有类型相同的excel,可以
- 本文以实例形式详细讲述了Java的反射机制,是Java程序设计中重要的技巧。分享给大家供大家参考。具体分析如下:首先,Reflection是
- 一、概念 工厂方法模式是类的创建模式,又叫虚
- 今天再学习一些C#的基础知识,如对 Int Array进行排序:你可以在控制台应用程序中,创建一个类别,它属性和2个构造函数:Source
- 一、何为栈?栈(stack)又名堆栈,它是一种运算受限的线性表。限定仅在表尾进行插入和删除操作的线性表。这一端被称为栈顶,相对地,把另一端称
- C#生成指定范围内的不重复随机数// Number随机数个数// minNum随机数下限// maxNum随机数上限public int[]
- 本文首先将会回顾Spring 5之前的SpringMVC异常处理机制,然后主要讲解Spring Boot 2 Webflux的全局异常处理机
- 一、基本定义Arrays类,全路径java.util.Arrays,主要功能为操作数组,Arrays类的所有方法均为静态方法,所以调用方式全
- SpringBoot读取外置logback配置文件springboot项目可以读取外置配置文件,避免了修改配置文件需要重新打包部署的问题。部