SpringBoot整合微信登录功能的实现方案

网友投稿 889 2022-11-27

SpringBoot整合微信登录功能的实现方案

SpringBoot整合微信登录功能的实现方案

目录1. OAuth2解决什么问题?2. 微信扫描登录2.1 添加必要的依赖2.2 application.properties 添加配置2.3 登录请求2.4 前端

1. OAuth2解决什么问题?

OAuth2:是针对特定问题一种解决方案

可以解决两个问题:

a. 开放系统间授权

b. 分布式访问问题

解决方案:

a. 方式一:用户名密码复制

b. 通用开发者key

c. 办法令牌

2. 微信扫描登录

点击进行注册开发者认证

JWT配置

2.1 添加必要的依赖

org.apache.httpcomponents

httpclient

commons-io

commons-io

com.google.code.gson

gson

2.2 application.properties 添加配置

下面的配置是你申请的有关的,重定向链接是登陆成功需要跳转的请求

# 微信开放平台 appid

wx.open.app_id=wxed94c01bb89b47

# 微信开放平台 appsecret

wx.open.app_secret=a7482517235173ddb43788de60b90e

# 微信开放平台 重定向url

wx.open.redirect_url=http://localhost:8160/api/ucenter/wx/callback

2.3 登录请求

//1 生成微信扫描二维码

@GetMapping("login")

public String getWxCode() {

System.out.println("调用了兄弟。。。。。。。。。。。。。。。。。。。。。。。。。。。。。");

//固定地址,后面拼接参数

// String url = "https://open.weixin.qq.com/" +

// "connect/qrconnect?appid="+ ConstantWxUtils.WX_OPEN_APP_ID+"&response_type=code";

// 微信开放平台授权baseUrl %s相当于?代表占位符

String baseUrl = "https://open.weixin.qq.com/connect/qrconnect" +

"?appid=%s" +

"&redirect_uri=%s" +

"&response_type=code" +

"&scope=snsapi_login" +

"&state=%s" +

"#wechat_redirect";

//对redirect_url进行URLEncoder编码

String redirectUrl = ConstantWxUtils.WX_OPEN_REDIRECT_URL;

try {

redirectUrl = URLEncoder.encode(redirectUrl, "utf-8");

}catch(Exception e) {

}

//设置%s里面值

String url = String.format(

baseUrl,

ConstantWxUtils.WX_OPEN_APP_ID,

redirectUrl,

"atguigu"

);

//重定向到请求微信地址里面

return "redirect:"+url;

}

请求成功后,扫描二维码点击缺点登录

会自动调用callback

//2 获取扫描人信息,添加数据

@GetMapping("callback")

public String callback(String code, String state) {

try {

//1 获取code值,临时票据,类似于验证码

//2 拿着code请求 微信固定的地址,得到两个值 accsess_token 和 openid

String baseAccessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token" +

"?appid=%s" +

"&secret=%s" +

"&code=%s" +

"&grant_type=authorization_code";

//拼接三个参数 :id 秘钥 和 code值

String accessTokenUrl = String.format(

baseAccessTokenUrl,

ConstantWxUtils.WX_OPEN_APP_ID,

ConstantWxUtils.WX_OPEN_APP_SECRET,

code

);

//请求这个拼接好的地址,得到返回两个值 accsess_token 和 openid

//使用httpclient发送请求,得到返回结果

String accessTokenInfo = HttpClientUtils.get(accessTokenUrl);

//从accessTokenInfo字符串获取出来两个值 accsess_token 和 openid

//把accessTokenInfo字符串转换map集合,根据map里面key获取对应值

//使用json转换工具 Gson

Gson gson = new Gson();

HashMap mapAccessToken = gson.fromJson(accessTokenInfo, HashMap.class);

String access_token = (String)mapAccessToken.get("access_token");

String openid = (String)mapAccessToken.get("openid");

//把扫描人信息添加数据库里面

//判断数据表里面是否存在相同微信信息,根据openid判断

UcenterMember member = memberService.getOpenIdMember(openid);

if(member == null) {//memeber是空,表没有相同微信数据,进行添加

//3 拿着得到accsess_token 和 openid,再去请求微信提供固定的地址,获取到扫描人信息

//访问微信的资源服务器,获取用户信息

String baseUserInfoUrl = "https://api.weixin.qq.com/sns/userinfo" +

"?access_token=%s" +

"&openid=%s";

//拼接两个参数

String userInfoUrl = String.format(

baseUserInfoUrl,

access_token,

openid

);

//发送请求

String userInfo = HttpClientUtils.get(userInfoUrl);

System.out.println("userInfo::::"+userInfo);

//获取返回userinfo字符串扫描人信息

HashMap userInfoMap = gson.fromJson(userInfo, HashMap.class);

String nickname = (String)userInfoMap.get("nickname");//昵称

String headimgurl = (String)userInfoMap.get("headimgurl");//头像

member = new UcenterMember();

member.setOpenid(openid);

member.setNickname(nickname);

member.setAvatar(headimgurl);

memberService.save(member);

}

//使用jwt根据member对象生成token字符串

String jwtToken = JwtUtils.getJwtToken(member.getId(), member.getNickname());

//最后:返回首页面,通过路径传递token字符串

return "redirect:http://localhost:3000?token="+jwtToken;

}catch(Exception e) {

throw new GuliException(20001,"登录失败");

}

}

查找用户信息根据token

//根据token获取用户的信息

@GetMapping("getmemberInfo")

public R getmemberInfo(HttpServletRequest request){

//调用jwt工具类,根据request对象获取头部信息

//获的用户的id

String memberId = JwtUtils.getMemberIdByJwtToken(request);

UcenterMember ucenterMember = memberService.getById(memberId);

return R.ok().data("userInfo",ucenterMember);

}

ConstantWxUtils 获取配置文件的值

@Component

public class ConstantWxUtils implements InitializingBean {

@Value("${wx.open.app_id}")

private String appId;

@Value("${wx.open.app_secret}")

private String appSecret;

@Value("${wx.open.redirect_url}")

private String redirectUrl;

public static String WX_OPEN_APP_ID;

public static String WX_OPEN_APP_SECRET;

public static String WX_OPEN_REDIRECT_URL;

@Override

public void afterPropertiesSet() throws Exception {

WX_OPEN_APP_ID = appId;

WX_OPEN_APP_SECRET = appSecret;

WX_OPEN_REDIRECT_URL = redirectUrl;

}

}

HttpClientUtils

public class HttpClientUtils {

public static final int connTimeout=10000;

public static final int readTimeout=10000;

public static final String charset="UTF-8";

private static HttpClient client = null;

static {

PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();

cm.setMaxTotal(128);

cm.setDefaultMaxPerRoute(128);

client = HttpClients.custom().setConnectionManager(cm).build();

}

public static String postParameters(String url, String parameterStr) throws ConnectTimeoutException, SocketTimeoutException, Exception{

return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);

}

public static String postParameters(String url, String parameterStr,String charset, Integer connTimeout, Integer readTimeout) throws ConnectTimeoutException, SocketTimeoutException, Exception{

return post(url,parameterStr,"application/x-www-form-urlencoded",charset,connTimeout,readTimeout);

}

public static String postParameters(String url, Map params) throws ConnectTimeoutException,

SocketTimeoutException, Exception {

return postForm(url, params, null, connTimeout, readTimeout);

}

public static String postParameters(String url, Map params, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,

SocketTimeoutException, Exception {

return postForm(url, params, null, connTimeout, readTimeout);

}

public static String get(String url) throws Exception {

return get(url, charset, null, null);

}

public static String get(String url, String charset) throws Exception {

return get(url, charset, connTimeout, readTimeout);

}

/**

* 发送一个 Post 请求, 使用指定的字符集编码.

*

* @param url

* @param body RequestBody

* @param mimeType 例如 application/xml "application/x-www-form-urlencoded" a=1&b=2&c=3

* @param charset 编码

* @param connTimeout 建立链接超时时间,毫秒.

* @param readTimeout 响应超时时间,毫秒.

* @return ResponseBody, 使用指定的字符集编码.

* @throws ConnectTimeoutException 建立链接超时异常

* @throws SocketTimeoutException 响应超时

* @throws Exception

*/

public static String post(String url, String body, String mimeType,String charset, Integer connTimeout, Integer readTimeout)

throws ConnectTimeoutException, SocketTimeoutException, Exception {

HttpClient client = null;

HttpPost post = new HttpPost(url);

String result = "";

try {

if (StringUtils.isNotBlank(body)) {

HttpEntity entity = new StringEntity(body, ContentType.create(mimeType, charset));

post.setEntity(entity);

}

// 设置参数

Builder customReqConf = RequestConfig.custom();

if (connTimeout != null) {

customReqConf.setConnectTimeout(connTimeout);

}

if (readTimeout != null) {

customReqConf.setSocketTimeout(readTimeout);

}

post.setConfig(customReqConf.build());

HttpResponse res;

if (url.startsWith("https")) {

// 执行 Https 请求.

client = createSSLInsecureClient();

res = client.execute(post);

} else {

// 执行 Http 请求.

client = HttpClientUtils.client;

res = client.execute(post);

}

result = IOUtils.toString(res.getEntity().getContent(), charset);

} finally {

post.releaseConnection();

if (url.startsWith("https") && client != null&& client instanceof CloseableHttpClient) {

((CloseableHttpClient) client).close();

}

}

return result;

}

/**

* 提交form表单

*

* @param url

* @param params

* @param connTimeout

* @param readTimeout

* @return

* @throws ConnectTimeoutException

* @throws SocketTimeoutException

* @throws Exception

*/

public static String postForm(String url, Map params, Map headers, Integer connTimeout,Integer readTimeout) throws ConnectTimeoutException,

SocketTimeoutException, Exception {

HttpClient client = null;

HttpPost post = new HttpPost(url);

try {

if (params != null && !params.isEmpty()) {

List formParams = new ArrayList();

Set> entrySet = params.entrySet();

for (Entry entry : entrySet) {

formParams.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));

}

UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formParams, Consts.UTF_8);

post.setEntity(entity);

}

if (headers != null && !headers.isEmpty()) {

for (Entry entry : headers.entrySet()) {

post.addHeader(entry.getKey(), entry.getValue());

}

}

// 设置参数

Builder customReqConf = RequestConfig.custom();

if (connTimeout != null) {

customReqConf.setConnectTimeout(connTimeout);

}

if (readTimeout != null) {

customReqConf.setSocketTimeout(readTimeout);

}

post.setConfig(customReqConf.build());

HttpResponse res = null;

if (url.startsWith("https")) {

// 执行 Https 请求.

client = createSSLInsecureClient();

res = client.execute(post);

} else {

// 执行 Http 请求.

client = HttpClientUtils.client;

res = client.execute(post);

}

return IOUtils.toString(res.getEntity().getContent(), "UTF-8");

} finally {

post.releaseConnection();

if (url.startsWith("https") && client != null

&& client instanceof CloseableHttpClient) {

((CloseableHttpClient) client).close();

}

}

}

/**

* 发送一个 GET 请求

*

* @param url

* @param charset

* @param connTimeout 建立链接超时时间,毫秒.

* @param readTimeout 响应超时时间,毫秒.

* @return

* @throws ConnectTimeoutException 建立链接超时

* @throws SocketTimeoutException 响应超时

* @throws Exception

*/

public static String get(String url, String charset, Integer connTimeout,Integer readTimeout)

throws ConnectTimeoutException,SocketTimeoutException, Exception {

HttpClient client = null;

HttpGet get = new HttpGet(url);

String result = "";

try {

// 设置参数

Builder customReqConf = RequestConfig.custom();

if (connTimeout != null) {

customReqConf.setConnectTimeout(connTimeout);

}

if (readTimeout != null) {

customReqConf.setSocketTimeout(readTimeout);

}

get.setConfig(customReqConf.build());

HttpResponse res = null;

if (url.startsWith("https")) {

// 执行 Https 请求.

client = createSSLInsecureClient();

res = client.execute(get);

} else {

// 执行 Http 请求.

client = HttpClientUtils.client;

res = client.execute(get);

}

result = IOUtils.toString(res.getEntity().getContent(), charset);

} finally {

get.releaseConnection();

if (url.startsWith("https") && client != null && client instanceof CloseableHttpClient) {

((CloseableHttpClient) client).close();

}

}

return result;

}

/**

* 从 response 里获取 charset

*

* @param ressponse

* @return

*/

@SuppressWarnings("unused")

private static String getCharsetFromResponse(HttpResponse ressponse) {

// Content-Type:text/html; charset=GBK

if (ressponse.getEntity() != null && ressponse.getEntity().getContentType() != null && ressponse.getEntity().getContentType().getValue() != null) {

String contentType = ressponse.getEntity().getContentType().getValue();

if (contentType.contains("charset=")) {

return contentType.substring(contentType.indexOf("charset=") + 8);

}

http:// }

return null;

}

/**

* 创建 SSL连接

* @return

* @throws GeneralSecurityException

*/

private static CloseableHttpClient createSSLInsecureClient() throws GeneralSecurityException {

try {

SSLContext sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {

public boolean isTrusted(X509Certificate[] chain,String authType) throws CertificateException {

return true;

}

}).build();

SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, new X509HostnameVerifier() {

@Override

public boolean verify(String arg0, SSLSession arg1) {

return true;

}

@Override

public void verify(String host, SSLSocket ssl)

throws IOException {

}

@Override

public void verify(String host, X509Certificate cert)

throws SSLException {

}

@Override

public void verify(String host, String[] cns,

String[] subjectAlts) throws SSLException {

}

});

return HttpClients.custom().setSSLSocketFactory(sslsf).build();

} catch (GeneralSecurityException e) {

throw e;

}

}

public static void main(String[] args) {

try {

String str= post("https://localhost:443/ssl/test.shtml","name=12&page=34","application/x-www-form-urlencoded", "UTF-8", 10000, 10000);

//String str= get("https://localhost:443/ssl/test.shtml?name=12&page=34","GBK");

/*Map map = new HashMap();

map.put("name", "111");

map.put("page", "222");

String str= postForm("https://localhost:443/ssl/test.shtml",map,null, 10000, 10000);*/

System.out.println(str);

} catch (ConnectTimeoutException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (SocketTimeoutException e) {

// TODO Auto-generated catch block

e.printStackTrace();

} catch (Exception e) {

// TODO Auto-generated catch block

e.printStackTrace();

}

}

}

2.4 前端

点击微信登录 发送请求

到二维码的界面

扫描后 点击登录

将后端传递的token值中的用户信息交给前端

created() {

//获取路径里面token值?后面的值

this.token = this.$route.query.token

console.log(this.token)

ttKgyqAD if(this.token) {//判断路径是否有token值

this.wxLogin()

}

},

//微信登录显示的方法

wxLogin() {

//console.log('************'+this.token)

//把token值放到cookie里面

cookie.set('guli_token',this.token,{domain: 'localhost'})

cookie.set('guli_ucenter','',{domain: 'localhost'})

//console.log('====='+cookie.get('guli_token'))

//调用接口,根据token值获取用户信息

loginApi.getLoginUserInfo()

.then(response => {

this.loginInfo = response.data.data.userInfo

cookie.set('guli_ucenter',this.loginInfo,{domain: 'localhost'})

})

},

版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。

上一篇:swoole 初试教程 锁机制
下一篇:swoole 初试教程 异步事件
相关文章

 发表评论

暂时没有评论,来抢沙发吧~