网站实现微信扫码登录+Java+Shiro 框架
一、准备工作
1、注册微信开放平台:https://open.weixin.qq.com/
2、创建网站应用 , 设置授权回调域。
3、开发者认证 (需要企业资质,费用300元)
二、具体实现步骤
1、网页页面生成二维码 ---- 使用第二种方式
步骤1:在页面中先引入如下JS文件(支持https):
http://res.wx.qq.com/connect/zh_CN/htmledition/js/wxLogin.js步骤2:在需要使用微信登录的地方实例以下JS对象:var obj = new WxLogin({self_redirect:true,id:"login_container", appid: "", scope: "", redirect_uri: "",state: "",style: "",href: ""});
2、通过code获取access_token(服务端实现)
https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code
3、第三步:获取用户个人信息(UnionID机制) (服务端实现)
https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID
4、获取到 unionID , 到 sys_user 用户表进行查找用户是否存在
5、用户存在,直接登录
6、用户不存在,进入到提示注册页面
7、使用步骤1生成二维码时,可先从服务端返回对应的参数
@RequestMapping(value = "/pre")@ResponseBodypublic Map<String,String> pre(HttpServletRequest request){Map<String,String> map = new HashMap<String, String>();map.put("AppId", Global.getConfig("weixin.open.AppId"));map.put("redirect_url", Global.getConfig("weixin.open.redirect_url"));map.put("state", IdGen.uuid().toUpperCase());String key =map.get("state");WechatCacheUtils.put(key, key);return map;}
8、伪代码逻辑如下:
@SuppressWarnings("unchecked")@RequestMapping(value = "/login")public Object login(String code ,String state , Model model , HttpServletRequest request) throws IOException {if(StringUtils.isBlank(code) || StringUtils.isBlank(state)) {model.addAttribute("message","state or code 参数错误!");return "error/invalid";}logger.debug("code , {}" , code);logger.debug("state , {}" , state);String key =state;Object attribute = WechatCacheUtils.get(key);// 1、state 参数校验if(null == attribute || !state.equals(attribute.toString())) {model.addAttribute("message","非法请求!");return "error/invalid";}WechatCacheUtils.remove(key);// 2、获取AccessTokenString openAccessToken = WechatCacheUtils.getOpenAccessToken(code);logger.debug("openAccessToken , {}" , openAccessToken);Map<String,String> resMap = (Map<String,String>)JsonMapper.fromJsonString(openAccessToken, Map.class);// 3、获取用户个人信息 String url = WechatConstant.WEIXIN_OPEN_USERINFO.concat("access_token=").concat(resMap.get("access_token")).concat("&openid=").concat(resMap.get("openid"));logger.debug("获取用户个人信息url, {}" , url);Map<String,String> res = new HashMap<String, String>();String doGet = null ;try {doGet = HttpClientUtils.doGet(url);logger.debug("获取用户个人信息,如下: {}" , doGet);res = (Map<String,String>)JsonMapper.fromJsonString(doGet, Map.class);} catch (IOException e) {e.printStackTrace();}if(StringUtils.isBlank(res.get("unionid"))) {// 接口调用失败,无法获取到 unionidlogger.error("获取用户信息失败, 用户信息接口返回数据如下: {}" , doGet);model.addAttribute("message","微信接口错误,请重试!");return "error/invalid";}User temp = new User();temp.setWechatUid(res.get("unionid"));temp.setNumber(1);// 4、根据用户唯一标识,判断是否存在 wechatUidList<User> findList = systemService.existsUserByCondition(temp);if(CollectionUtils.isEmpty(findList)) {// 不存在,跳转到提示到小程序注册页面return "modules/sys/guideWechat";}// 存在,调用shiro 进行登录 Subject subject = SecurityUtils.getSubject();UsernamePasswordToken passwordToken = new UsernamePasswordToken();passwordToken.setUsername(findList.get(0).getLoginName());passwordToken.setPassword(findList.get(0).getPassword().toCharArray());passwordToken.setUnpass(true); // 免密码登录验证subject.login(passwordToken);// 登录成功,跳转到登录管理页面return "redirect:"+adminPath+"/login";}
三、总结
1、创建网站应用步骤 --- 授权回调域 , 可以随便修改,且及时生效的。
2、本地调试办法,使用内网穿透,映射一个本地地址即可。参考: Java 微信支付通知本地调试解决办法
3、扫码登录后,若网站使用shiro作为登录管理,建议参考: Shiro实现免密码登录。
4、调试的时候,可以使用第一种方法生成二维码,无需校验state
https://open.weixin.qq.com/connect/qrconnect?appid=APPID&redirect_uri=REDIRECT_URI&response_type=code&scope=SCOPE&state=STATE#wechat_redirect
若不明白,欢迎留言沟通,谢谢~
参考资料: Java后端调用其他服务接口
Shiro 实现免密码登录策略