我页面使用了生成二维码的js,是网上拿到的(太多转载,具体作者是啥不知道(#^.^#))

点击打开生成二维码js链接  直接复制js就OK。

好,正文来啦,我代码中是使用了springboot(SSM)+redis+shiro。。。

页面代码:

<!DOCTYPE html>
<html lang="zh_CN" xmlns:th="http://www.thymeleaf.org"xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head><meta charset="UTF-8"/><title>微信登录二维码</title><script src='/js/jquery-2.0.3.min.js'></script><script src="/js/qrcode.js"></script><script type="text/javascript">/*<![CDATA[*/function checkLogin(){var i = 0;var sessionId = $("#sessionId").val();if(sessionId!=""){$.ajax({url: "/wechat/polling",type: "POST",data:{sessionId:sessionId},success: function (data) {if(data.status=="200"){window.clearInterval(c);alert(data.message);location.href = "/";}else{i++;if(i>60){window.clearInterval(c);alert("二维码已失效!请刷新二维码。");}}}});}}function wechatLogin(){$.ajax({url: "/wechat/wxLoginPage",type: "POST",success: function (data) {$("#sessionId").val(data.sessionId);var qrcode = new QRCode(document.getElementById("code"), {width : 200,//设置宽高height : 200});qrcode.makeCode(data.uri);c = setInterval(checkLogin,5000);//轮询查询}});}/*]]>*/</script>
</head>
<body><shiro:guest><input type="button" value="微信登录" onclick="wechatLogin()" /></shiro:guest><shiro:user><shiro:principal property="username" />您已登录。</shiro:user><input type="hidden" id="sessionId"/><br/><br/><br/><br/><div id="code"></div>
</body>
</html>

后台controller(@RequestMapping("/wechat"))代码:

//pc点击微信登录,生成登录二维码@RequestMapping(value = "/wxLoginPage",method = RequestMethod.POST)@ResponseBodypublic Map<String,String> wxLoginPage(HttpServletRequest request) throws Exception {String sessionId = request.getSession().getId();logger.info("sessionId:"+sessionId);String uri = weChatAuthService.getAuthorizationUrl("pc",sessionId);//设置redirect_uri和state=sessionId以及测试号信息,返回授权urllogger.info(uri);Map<String,String> map = new HashMap<String,String>();map.put("sessionId", sessionId);map.put("uri", uri);//用来前端生成二维码return map;}//扫描二维码授权成功,取到code,回调方法@RequestMapping(value = "/pcAuth")@ResponseBodypublic String pcCallback(String code,String state,HttpServletRequest request,HttpServletResponse response) throws Exception {String result = weChatAuthService.getAccessToken(code);//根据code获取access_token和openId,不懂看微信文档JSONObject jsonObject = JSONObject.parseObject(result);//String refresh_token = jsonObject.getString("refresh_token");String access_token = jsonObject.getString("access_token");String openId = jsonObject.getString("openId");logger.info("------------授权成功----------------");JSONObject infoJson = weChatAuthService.getUserInfo(access_token,openId);//根据token和openId获取微信用户信息,不懂看我上一篇文章开始分享的链接if(infoJson!=null){String nickname = infoJson.getString("nickName");logger.info("-----nickname-----"+nickname);logger.info("-----sessionId-----"+state);infoJson.put("openId", openId);redisTemplate.opsForValue().set(state, infoJson, 10*60, TimeUnit.SECONDS);return "登录成功!";}return "登录失败!";}
//轮询查询key@RequestMapping(value="/polling",method=RequestMethod.POST)@ResponseBodypublic Map<String, Object> polling(String sessionId,HttpServletRequest request,HttpServletResponse response){Map<String, Object> resultMap = new LinkedHashMap<String, Object>();if(redisTemplate.hasKey(sessionId)){JSONObject infoJson = (JSONObject)redisTemplate.opsForValue().get(sessionId);redisTemplate.opsForValue().getOperations().delete(sessionId);String openId = (String)infoJson.get("openId");//根据openId判断我们网站是否存在该用户,数据库用户表会保存用户User user = userService.selectUserByWechat(openId);if (user == null) {String nickname = (String)infoJson.get("nickName");String sex = (String)infoJson.get("sex");User newuser = new User();newuser.setSex(sex);newuser.setWechat(openId);newuser.setNickname(nickname);int i = userService.insertUser(newuser);//新增用户if(i<1){resultMap.put("status", 500);resultMap.put("message", "登录失败:");return resultMap;}}//登录操作try {UsernamePasswordToken token = new UsernamePasswordToken(openId, openId);//这里是用shiro登录,反正该openId已经微信扫码验证SecurityUtils.getSubject().login(token);resultMap.put("status", 200);resultMap.put("message", "登录成功");//更新用户最后登录时间Subject  currentUser = SecurityUtils.getSubject(); User luser = (User) currentUser.getPrincipal();User user1 = new User();user1.setId(luser.getId());user1.setLastLogDate(new Date());userService.updateUserByIdSelective(user1);//更新用户方法} catch (Exception e) {resultMap.put("message", "未知系统错误:" + e.getMessage());}return resultMap;}else{//not has keyresultMap.put("status", 0);return resultMap;}}

serviceImpl代码

package com.kun.service.impl;import java.io.UnsupportedEncodingException;
import java.net.URI;
import java.net.URLEncoder;import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.util.UriComponentsBuilder;import com.alibaba.fastjson.JSONObject;
import com.kun.service.WeChatAuthService;@Service
public class WeChatAuthServiceImpl extends DefaultAuthServiceImpl implements WeChatAuthService {private final Logger logger = LoggerFactory.getLogger(this.getClass());//请求此地址即跳转到二维码登录界面private static final String AUTHORIZATION_URL ="https://open.weixin.qq.com/connect/oauth2/authorize?appid=%s&redirect_uri=%s&response_type=code&scope=%s&state=%s#wechat_redirect";// 获取用户 openid 和access——toke 的 URLprivate static final String ACCESSTOKE_OPENID_URL ="https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code";private static final String REFRESH_TOKEN_URL ="https://api.weixin.qq.com/sns/oauth2/refresh_token?appid=%s&grant_type=refresh_token&refresh_token=%s";private static final String USER_INFO_URL ="https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=zh_CN";private static final String APP_ID="wx957421889a04804d";private static final String APP_SECRET="9155791266381e14c670ea7fa1abb90b";private static final String SCOPE = "snsapi_userinfo";//  snsapi_userinfo  snsapi_baseprivate String pcCallbackUrl = "https://7dc6440a.ngrok.io//wechat/pcAuth"; //pc回调域名private String mobileCallbackUrl = "https://7dc6440a.ngrok.io//wechat/mobileAuth"; //mobile回调域名/*** 第一步,带着参数* appid:公众号的唯一标识* redirect_uri:授权后重定向的回调链接地址* response_type:返回类型,填写code* scope:应用授权作用域,snsapi_base / snsapi_userinfo* state:非必传,重定向后会带上state参数,开发者可以填写a-zA-Z0-9的参数值,最多128字节* wechat_redirect:无论直接打开还是做页面302重定向时候,必须带此参数* */@Overridepublic String getAuthorizationUrl(String type,String state) throws UnsupportedEncodingException {String callbackUrl = "";Object urlState = "";if("pc".equals(type)){//移动端 pc端回调方法不一样 callbackUrl = URLEncoder.encode(pcCallbackUrl,"utf-8");urlState = state;}else if("mobile".equals(type)){callbackUrl = URLEncoder.encode(mobileCallbackUrl,"utf-8");urlState = System.currentTimeMillis();}String url = String.format(AUTHORIZATION_URL,APP_ID,callbackUrl,SCOPE,urlState);return url;}/*** 第二步* 传appid  secret code grant_type=authorization_code* 获得 access_token openId等* */@Overridepublic String getAccessToken(String code) {String url = String.format(ACCESSTOKE_OPENID_URL,APP_ID,APP_SECRET,code);UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);URI uri = builder.build().encode().toUri();String resp = getRestTemplate().getForObject(uri, String.class);logger.error("getAccessToken resp = "+resp);if(resp.contains("openid")){JSONObject jsonObject = JSONObject.parseObject(resp);String access_token = jsonObject.getString("access_token");String openId = jsonObject.getString("openid");;JSONObject res = new JSONObject();res.put("access_token",access_token);res.put("openId",openId);res.put("refresh_token",jsonObject.getString("refresh_token"));return res.toJSONString();}else{logger.error("获取用户信息错误,msg = "+resp);return null;}}//微信接口中,token和openId是一起返回,故此方法不需实现@Overridepublic String getOpenId(String accessToken) {return null;}@Overridepublic JSONObject getUserInfo(String accessToken, String openId){String url = String.format(USER_INFO_URL, accessToken, openId);UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);URI uri = builder.build().encode().toUri();String resp = getRestTemplate().getForObject(uri, String.class);logger.error("getUserInfo resp = "+resp);if(resp.contains("errcode")){logger.error("获取用户信息错误,msg = "+resp);return null;}else{JSONObject data =JSONObject.parseObject(resp);JSONObject result = new JSONObject();result.put("id",data.getString("unionid"));result.put("sex",data.getString("sex"));result.put("nickName",data.getString("nickname"));result.put("avatar",data.getString("headimgurl"));return result;}}//微信的token只有2小时的有效期,过时需要重新获取,所以官方提供了//根据refresh_token 刷新获取token的方法,本项目仅仅是获取用户//信息,并将信息存入库,所以两个小时也已经足够了@Overridepublic String refreshToken(String refresh_token) {String url = String.format(REFRESH_TOKEN_URL,APP_ID,refresh_token);UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(url);URI uri = builder.build().encode().toUri();ResponseEntity<JSONObject> resp = getRestTemplate().getForEntity(uri,JSONObject.class);JSONObject jsonObject = resp.getBody();String access_token = jsonObject.getString("access_token");return access_token;}
}

上面实现类继承的类DefaultAuthServiceImpl

package com.kun.service.impl;import java.nio.charset.StandardCharsets;
import java.util.LinkedList;
import java.util.List;import javax.xml.transform.Source;import org.springframework.http.client.SimpleClientHttpRequestFactory;
import org.springframework.http.converter.ByteArrayHttpMessageConverter;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.ResourceHttpMessageConverter;
import org.springframework.http.converter.StringHttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.http.converter.support.AllEncompassingFormHttpMessageConverter;
import org.springframework.http.converter.xml.SourceHttpMessageConverter;
import org.springframework.web.client.RestTemplate;import com.kun.service.AuthService;public abstract class DefaultAuthServiceImpl implements AuthService{public static RestTemplate getRestTemplate() {// 手动添加SimpleClientHttpRequestFactory requestFactory=new SimpleClientHttpRequestFactory();requestFactory.setReadTimeout(120000);List<HttpMessageConverter<?>> messageConverters = new LinkedList<>();messageConverters.add(new ByteArrayHttpMessageConverter());messageConverters.add(new StringHttpMessageConverter(StandardCharsets.UTF_8));messageConverters.add(new ResourceHttpMessageConverter());messageConverters.add(new SourceHttpMessageConverter<Source>());messageConverters.add(new AllEncompassingFormHttpMessageConverter());messageConverters.add(new MappingJackson2HttpMessageConverter());RestTemplate restTemplate=new RestTemplate(messageConverters);restTemplate.setRequestFactory(requestFactory);return restTemplate;}
}------------------
package com.kun.service;import java.io.UnsupportedEncodingException;import com.alibaba.fastjson.JSONObject;public interface AuthService {public abstract String getAccessToken(String code);public abstract String getOpenId(String accessToken);public abstract String refreshToken(String code);public abstract String getAuthorizationUrl(String type,String state) throws UnsupportedEncodingException;public abstract JSONObject getUserInfo(String accessToken,String openId);
}

上一篇文章《微信测试号实现个人第三方PC端网站二维码登录》

到这里就可以实现微信二维码登录我们的个人网站啦~~~~~

微信测试号实现个人第三方PC端网站二维码登录(代码实现篇)相关推荐

  1. 微信测试号实现个人第三方PC端网站二维码登录

    这里只提及微信二维码登录PC网站的实现方面,对于微信测试号如何申请,如何授权,本篇博客不去讲解. 测试号申请:http://mp.weixin.qq.com/debug/cgi-bin/sandbox ...

  2. 百度网盘PC端扫描二维码登录时无法加载二维码问题解决方法

    问题: 今天在PC端扫描登录百度网盘时,二维码无法加载出来,具体情况如图: 解决方法: 1.打开IE浏览器 2.打开工具 3.打开Internet选项 4.打开高级选项,重置IE设置 5.点击确定,打 ...

  3. 扫描pc端页面二维码,在手机上签名

    npm install qrcodejs2 npm install signature_pad 在移动端需要安装 vant和jquery npm install vant npm install jq ...

  4. 浅谈扫描二维码登录微信网页版与摇一摇传图的实现原理

    前言:简单体验了下微信网页版通过二维码登录和摇一摇传图功能,从技术角度看,网上专家吹捧的 [隔空取物]其实并不神秘,我先简单分析一下. 1. 微信移动端扫描二维码登录(C-S-C模式) CSC模式为: ...

  5. 二维码登录原理+Web端即时通讯技术

    前言 上周在写项目过程中遇到需要实现二维码的登录功能,将这个过程细节记录下来 二维码的登录过程,主要难点在于用户扫码了浏览器展示的二维码,但是浏览器本身是无法知道的,需要服务端告知信息. 涉及到 we ...

  6. 微信扫描二维码登录第三方平台

    嗯...... 最近做了一个微信扫码登陆第三方平台功能,说下步骤就行,反正原理你们网上直接百度,我这里写了,估计也没几个人有耐心看 第一步 生成一个链接 https://open.weixin.qq. ...

  7. springboot微信支付pc页面生成二维码

    微信支付开发文档:https://pay.weixin.qq.com/wiki/doc/api/index.html 咱们这次采用的是Native支付 Native支付使用场景:用户打开"微 ...

  8. Android安卓开发集成微信第三方扫描二维码登录-超级无敌具详细

    Android安卓开发中集成微信二维码登录的步骤: 写在前面的: 该教程使用AS作为演示,使用ecplise请参照微信官方文档下载相应jar等所需参考文档和资源.在最后,我会附上这个Activity的 ...

  9. 跨端扫码确认实现Web登录(扫二维码登录)

    起初的想法是类似于QQ扫码登录,BILIBILI扫码登录一样,通过手机确认后,在web端重定向完成登录 通过对BILIBILI扫码功能的解析,自己实现了一套类似扫码登录的功能 以下为伪代码,仅供查阅 ...

最新文章

  1. 多目标跟踪:CVPR2019论文阅读
  2. 布局欧洲,挺进南美,比特币现金(BCH)再度攻下4个新市场
  3. 网页加载出现没有合适的负载均衡器_终于讲清楚了,什么是负载均衡(Load balancing)...
  4. Linux 进程(二) 进程地址空间
  5. MySQL 后from多个表_MYSQL回顾(多表查询相关)
  6. java md5 utf-8_Jquery与java MD5加密不同
  7. 跨数据库跨系统,数据脱敏有新招
  8. AutoResetEvent和ManualResetEvent的区别
  9. 后缀为.vep文件转换成.mp4文件
  10. N卡显卡驱动更新,解决色彩准确度增强的问题
  11. 德州农工大学计算机专业如何,德州农工大学美国排名
  12. vue中控制浏览器滚动
  13. 智慧金融系统软件需求规格说明(IEEE 830 标准)最终版
  14. 2019年1-6月网络安全态势分析及建议
  15. 无法将类 XXX中的构造器 XXX应用到给定类型
  16. 【漏洞发现-sql注入】有回显注入--sqli-labs
  17. 网络编程-基于MFC的仿QQ聊天室-2020
  18. transform:rotate兼容
  19. lotus notes
  20. 【小技巧】Android手机通知栏广告去除方法

热门文章

  1. 设计模式:(代理模式)
  2. 多线程并行和并发区别的简单理解
  3. 小福利,excel里面的subtotal函数的高级运用
  4. AEE-ADAPTIVE Emulation Environment
  5. Katalon之介绍及安装_辉机(第一篇)
  6. 免费高速图床————学习通网盘
  7. 项目中的图片跨域问题解决方式
  8. 使用POI实现EXcel表格的读写
  9. 使用ansible离线安装rpm包
  10. 输入1,2,3,输出321的方法