Spring boot 项目(十二)——实现电脑网页微信扫码自动授权

Spring boot 项目(十二)——实现电脑网页微信扫码自动授权,第1张

Spring boot 项目(十二)——实现电脑网页微信扫码自动授权 引言

电脑端微信网页扫码授权登录有2种方式:
第一种:基于微信公众号,单独获取登录二维码扫码,然后扫码登录,程序控制跳转逻辑,例如CSDN
第二种:基于微信开放平台,跳转到微信二维码页面进行扫码登录,重定向到成功页面,例如有道笔记

本文则是实现第一种授权登录

前期准备 内网渗透=>生成本地指定端口映射的外网域名

链接:内网渗透工具natapp使用详解
域名生成之后修改yml文件配置

申请并配置微信测试公众号

01、链接:点击申请微信测试公众号,并扫码关注测试公众号
02、备份appID和appsecret,后面需要用
03、接口配置信息修改(注:此处会回调后台签名验证方法,配置时需启动后台)

04、配置网页授权域名,用于获取微信用户信息

编写代码

Maven依赖:

        
            org.apache.httpcomponents
            httpclient
        
        
            com.alibaba
            fastjson
            1.2.54
        
        
        
            com.github.binarywang
            weixin-java-mp
            4.1.0
        
        
        
            com.github.binarywang
            weixin-java-common
            4.1.0
        

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:



微信扫码登录方式一




微信扫码登录方式二

controller层:

    @Autowired
    private WxConfig wxConfig;

    // 模拟数据库存储或者缓存存储
    Map loginMap = new ConcurrentHashMap<>(64);

    
    @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());
        }
    }
    
    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 ;
    }

    
    @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();
        }
    }


    
    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);
    }

    
    @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、第二张结果图只有在隧道运行状态正常时扫码才会出来,离线状态则无反应

附:源码

电脑网页微信扫码自动授权

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5696861.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-17
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存