电脑端微信网页扫码授权登录有2种方式:
第一种:基于微信公众号,单独获取登录二维码扫码,然后扫码登录,程序控制跳转逻辑,例如CSDN
第二种:基于微信开放平台,跳转到微信二维码页面进行扫码登录,重定向到成功页面,例如有道笔记
本文则是实现第一种授权登录
链接:内网渗透工具natapp使用详解
域名生成之后修改yml文件配置
01、链接:点击申请微信测试公众号,并扫码关注测试公众号
02、备份appID和appsecret,后面需要用
03、接口配置信息修改(注:此处会回调后台签名验证方法,配置时需启动后台)
04、配置网页授权域名,用于获取微信用户信息
Maven依赖:
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version>1.2.54</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-mp -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-mp</artifactId>
<version>4.1.0</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.github.binarywang/weixin-java-common -->
<dependency>
<groupId>com.github.binarywang</groupId>
<artifactId>weixin-java-common</artifactId>
<version>4.1.0</version>
</dependency>
yml文件:
spring:
thymeleaf:
cache: false
wx:
appId: wxb7ca6048ec426f03
appSecret: d29708209e6e4707431bbd8cd314396e
server: http://au3sic.natappfree.cc
qrCodeUrl: https://api.weixin.qq.com/cgi-bin/qrcode/create?access_token=TOKEN
tokenUrl: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET
openIdUrl: https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=APPID&secret=SECRET
userInfoUrl: https://api.weixin.qq.com/sns/userinfo?access_token=ACCESS_TOKEN&openid=OPENID&lang=zh_CN
HTML:
<body style="text-align: center;margin-top: 100px;">
<h1>微信扫码登录方式一</h1>
<button onclick="getQrCode()" style="width: 100px;height: 50px;">获取二维码</button>
<br>
<img src="" id="qrCodeImgId" style="width: 300px;height: 300px;display: none">
<hr>
<h1>微信扫码登录方式二</h1>
<button onclick="toQrCode()" style="width: 100px;height: 50px;">获取二维码</button>
<script>
//======================================微信扫码登录方式一=========================================================
// 存储二维码标识,用于验证是否扫码成功
var sceneStr;
var t;
// 获取登录二维码
function getQrCode(){
$.get('qrCodeFirstLogin/getQrCode',function (data) {
console.log("=============getQrCode=======================");
console.log(data);
if(data.code == 200){
sceneStr = data.data.sceneStr;
$('#qrCodeImgId').attr('src',"https://mp.weixin.qq.com/cgi-bin/showqrcode?ticket="+data.data.ticket);
$('#qrCodeImgId').show();
t = window.setInterval(getOpenId,3000);
}else{
alert(data.msg);
}
});
}
// 扫码成功,获取用户openId=>为获取用户信息做准备
function getOpenId() {
$.get("qrCodeFirstLogin/getOpenId",{
"eventKey":sceneStr
},function (data) {
if(data.code == 200){
console.log("========getOpenId==========");
console.log(data.data);
window.clearInterval(t);
alert("登录成功openId:"+data.data.openId);
/**
* 1、第一次扫码登录进行账号绑定
* 2、以后根据openId获取用户信息
*/
}
});
}
</script>
</body>
controller层:
@Autowired
private WxConfig wxConfig;
// 模拟数据库存储或者缓存存储
Map<String, CodeLoginKey> loginMap = new ConcurrentHashMap<>(64);
/**
* 获取登录二维码
* @return
*/
@RequestMapping("/getQrCode")
private Object getQrCode(){
try {
log.info("获取二维码ing。。。");
// 获取token开发者
String accessToken =getAccessToken();
String getQrCodeUrl = wxConfig.getQrCodeUrl().replace("TOKEN", accessToken);
// 这里生成一个带参数的二维码,参数是scene_str
String sceneStr = CodeLoginUtil.getRandomString(8);
String json="{\"expire_seconds\": 604800, \"action_name\": \"QR_STR_SCENE\"" +", \"action_info\": {\"scene\": {\"scene_str\": \""+sceneStr+"\"}}}";
String result = HttpClientUtil.doPostJson(getQrCodeUrl,json);
JSONObject jsonObject = JSONObject.parseObject(result);
jsonObject.put("sceneStr",sceneStr);
return ResultJson.ok(jsonObject);
} catch (Exception e) {
e.printStackTrace();
return ResultJson.failure(ResultCode.GENERATOR_FAILURE,e.getMessage());
}
}
/**
* 获取accessToken
* @return
*/
public String getAccessToken(){
String accessToken = null;
String getTokenUrl = wxConfig.getTokenUrl().replace("APPID", wxConfig.getAppId()).replace("SECRET", wxConfig.getAppSecret());
String result = HttpClientUtil.doGet(getTokenUrl);
JSONObject jsonObject = JSONObject.parseObject(result);
accessToken = jsonObject.getString("access_token");
return accessToken ;
}
/**
* 验证签名
* @param request
* @return
* @throws Exception
*/
@RequestMapping("/checkSign")
public String checkSign ( HttpServletRequest request) throws Exception {
log.info("===========>checkSign");
//获取微信请求参数
String signature = request.getParameter ("signature");
String timestamp = request.getParameter ("timestamp");
String nonce = request.getParameter ("nonce");
String echostr = request.getParameter ("echostr");
//参数排序。 token 就要换成自己实际写的 token
String [] params = new String [] {timestamp,nonce,"123456"} ;
Arrays.sort (params) ;
//拼接
String paramstr = params[0] + params[1] + params[2] ;
//加密
//获取 shal 算法封装类
MessageDigest Sha1Dtgest = MessageDigest.getInstance("SHA-1") ;
//进行加密
byte [] digestResult = Sha1Dtgest.digest(paramstr.getBytes ("UTF-8"));
//拿到加密结果
String mysignature = CodeLoginUtil.bytes2HexString(digestResult);
mysignature=mysignature.toLowerCase(Locale.ROOT);
//是否正确
boolean signsuccess = mysignature.equals(signature);
//逻辑处理
if (signsuccess && echostr!=null) {
//peizhi token
return echostr ;//不正确就直接返回失败提示.
}else{
JSONObject jsonObject = callback(request);
return jsonObject.toJSONString();
}
}
/**
* 回调方法
* @param request
* @return
* @throws Exception
*/
public JSONObject callback(HttpServletRequest request) throws Exception{
log.info("===========>callback");
//request中有相应的信息,进行解析
WxMpXmlMessage message= WxMpXmlMessage.fromXml(request.getInputStream());//获取消息流,并解析xml
String messageType=message.getMsgType(); //消息类型
String messageEvent=message.getEvent(); //消息事件
// openid
String fromUser=message.getFromUser(); //发送者帐号
String touser=message.getToUser(); //开发者微信号
String text=message.getContent(); //文本消息 文本内容
// 生成二维码时穿过的特殊参数
String eventKey=message.getEventKey(); //二维码参数
String uuid=""; //从二维码参数中获取uuid通过该uuid可通过websocket前端传数据
String userid="";
//if判断,判断查询
JSONObject jsonObject = new JSONObject();
jsonObject.put("code","200");
if(messageType.equals("event")){
jsonObject = null;
//先根据openid从数据库查询 => 从自己数据库中查取用户信息 => jsonObject
if(messageEvent.equals("SCAN")){
//扫描二维码
//return "欢迎回来";
}
if(messageEvent.equals("subscribe")){
//关注
//return "谢谢您的关注";
}
//没有该用户
if(jsonObject==null){
//从微信上中拉取用户信息
String url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token=" +getAccessToken() +
"&openid=" + fromUser +
"&lang=zh_CN";
String result = HttpClientUtil.doGet(url);
jsonObject = JSONObject.parseObject(result);
/**
* 用户信息处理....
*/
}
// 扫码成功,存入缓存
loginMap.put(eventKey,new CodeLoginKey(eventKey,fromUser));
return jsonObject;
}
return jsonObject;
//log.info("消息类型:{},消息事件:{},发送者账号:{},接收者微信:{},文本消息:{},二维码参数:{}",messageType,messageEvent,fromUser,touser,text,eventKey);
}
/**
* 根据二维码标识获取用户openId=>获取用户信息
* @param eventKey
* @return
*/
@RequestMapping("getOpenId")
public ResultJson getOpenId(String eventKey){
if(loginMap.get(eventKey) == null){
return ResultJson.failure(ResultCode.OPERATE_ERROR,"未扫码成功!") ;
}
CodeLoginKey codeLoginKey = loginMap.get(eventKey);
loginMap.remove(eventKey);
return ResultJson.ok(codeLoginKey);
}
}
由于篇幅有限,我就不放上去了。文章末尾会奉上源码作为参考。
注:
1、测试是在浏览器中进行,输入的网址是:localhost:8080
2、第二张结果图只有在隧道运行状态正常时扫码才会出来,离线状态则无反应本人的另一篇关于微信开发的博客:
Spring boot 项目(十三)——实现微信公众号授权登录获取用户信息
电脑网页微信扫码自动授权