微信面密登录。。网页授权

一.在页面加入标签

1.在登录页准备微信登录的按钮

<li><a href="https://open.weixin.qq.com/connect/qrconnect?
appid=wxd853562a0548a7d0&redirect_uri=http://bugtracker.itsource.cn/callback.html
&response_type=code&scope=snsapi_login&state=1#wechat_redirect"><i class="am-icon-weixin am-icon-sm"></i><span>微信登录</span> </a></li>
2.当用户点击微信扫码登录,向微信发起获取授权的请求

网址是,这个是为了获取code授权码的https://open.weixin.qq.com/connect/qrconnect? appid=wxd853562a0548a7d0&redirect_uri=http://bugtracker.itsource.cn/callback.html &response_type=code&scope=snsapi_login&state=1#wechat_redirect"><i class="am-icon-weixin am-icon-sm

redirect_uri=http://bugtracker.itsource.cn/callback.html 这个是回调域,授权成功后跳转的页面

3.微信收到确认,生成code(授权码),通过回调域拼接code返回,就获取到了code授权码了,

二.页面获取了code后,携带这个code发送请求到后台

1.后端接收请求和参数,在业务层处理请求

//code不为空
String code = map.get("code");
if(StringUtils.isEmpty(code)){
throw new MyException("系统异常。。。。");
}
String url = WxConstants.GET_TOKEN_URL.replace("APPID", WxConstants.APPID)
.replace("SECRET", WxConstants.SECRET)
.replace("CODE", code);
//根据code发送请求从微信获取token
/*{ 返回的是这个对象
"access_token":"ACCESS_TOKEN",
"expires_in":7200,
"refresh_token":"REFRESH_TOKEN",
"openid":"OPENID",
"scope":"SCOPE",
"unionid": "o6_bmasdasdsad6_2sgVt7hMZOPfL"
}*/
String obj = HttpClientUtils.httpGet(url);
JSONObject jsonObject = JSONObject.parseObject(obj);
//获取里面的token和openid
String token = jsonObject.getString("access_token");
String openid = jsonObject.getString("openid");
首先code不能为空,判断非空

再发送第二个请求,将第一步获取的code携带进去,然后获取token和openid

2.判断openid是否存在,通过查询数据库微信登录的表

2.1.如果已经有了并且userid不为空,直接免密登录

WxUser wxUser = wxUserMapper.loadByOpenId(openid);

String param = "?token="+token+"&openid="+openid;

if(wxUser!=null && wxUser.getUser_id()!=null){//之前登录过,直接放行
//查询对应的logininfo信息
Logininfo logininfo = logininfoMapper.loadByUserId(wxUser.getUser_id());

//登录过,将用户信息存到redis
//把用户信息放到redis key token
String token1 = UUID.randomUUID().toString();

//logininfo对象要存入数据库,必须序列化
redisTemplate.opsForValue().set(token1, logininfo, 30, TimeUnit.MINUTES);

Map<String, Object> map1 = new HashMap<>();

map1.put(Constant.TOKEN, token1);

//把私密信息设置为空
logininfo.setPassword(null);
logininfo.setSalt(null);
map1.put(Constant.LOGININFO, logininfo);
//map1.put("param", param);

return AjaxResult.createSuccess(map1);
}
2.2如果为空,需要让用户绑定个人用户信息
返回token+openId 前端帮我们跳转到绑定页面

return AjaxResult.createError("", param);
前端处理

let param = result.data;
//没有绑定,跳转到绑定页面
location.href="http://bugtracker.itsource.cn/binder.html"+param;
3.binder.html页面解析地址栏参数并且接收用户输入的参数

3.1发起微信绑定流程
phone verifyCode token openId

3.2后端接收参数交给service处理

String phone = map.get("phone");
String verifyCode = map.get("verifyCode");
String accessToken = map.get("accessToken");
String openId = map.get("openId");
//1.空校验
if(StringUtils.isEmpty(phone)
||StringUtils.isEmpty(verifyCode)
||StringUtils.isEmpty(accessToken)
||StringUtils.isEmpty(openId)){
throw new MyException("信息不能为空");
}
//2.判断验证码
//4.验证码是否过期 三分钟
Object o = redisTemplate.opsForValue().get(Constant.BINDER + phone);
if(o==null){
throw new MyException("验证码已失效,请重新获取。。。");
}
//5.前端输入的验证码和发送的是否一致
String code = o.toString().split(":")[0];
if(!verifyCode.equalsIgnoreCase(code)){
throw new MyException("验证码错误,请重新输入");
}
判断手机号是否注册过

//二:判断phone是否被注册 user
User user = userMapper.loadByPhone(phone);
User user1 = null;
Logininfo logininfo = null;
if(user!=null){
//1.如果注册了,那么我们可以直接绑定微信用户了
user1= user;
logininfo = logininfoMapper.loadByUserId(user1.getId());
}else {
//2.如果没有注册过,生成t_user + t_loginInfo + wxuser 三张表
user1 = initUser(phone);
logininfo = initLogininfo(user1);
//保存
logininfo.setType(1);
logininfoMapper.save(logininfo);
user1.setLogininfo_id(logininfo.getId());
userMapper.save(user1);

}
通过 token+openId 查询微信信息 wxuser 生成t_wxuser

//获取用户信息,保存在wxuser中
//https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
String obj = HttpClientUtils.httpGet(WxConstants.GET_USER_URL.replace("ACCESS_TOKEN", accessToken)
.replace("OPENID", openId));
WxUser wxUser = initWxuser(obj);
//绑定
wxUser.setUser_id(user1.getId());
wxUserMapper.save(wxUser);
//把用户信息放到redis key token
String token = UUID.randomUUID().toString();

//logininfo对象要存入数据库,必须序列化
redisTemplate.opsForValue().set(token, logininfo, 30, TimeUnit.MINUTES);

Map<String, Object> map2 = new HashMap<>();

map.put(Constant.TOKEN, token);

//把私密信息设置为空
logininfo.setPassword(null);
logininfo.setSalt(null);
map2.put(Constant.LOGININFO, logininfo);
return map2;
4.免密登录
完成
————————————————
版权声明:本文为CSDN博主「qq_42210156」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq_42210156/article/details/120060117

posted @ 2023-11-28 08:35  五百万  阅读(28)  评论(0编辑  收藏  举报