cas融合微信扫码企业微信扫码登录

总体逻辑:扫描二维码后在后端根据微信官方提供的API拿到用户openID,在进行判断是否存在该openID,存在返回用户账号密码(加密后)跳转至cas登录页面使用js触发自动登录,不存在跳转至绑定页面。

开发过程中细节问题:
1、cas不要过度的改动,不要破坏前人的代码逻辑,尽量只修改自己的二维码login页面和js即可,需要在md5加密部分代码判断是否为md5类型。
2、生成二维码微信和企业微信的默认样式不同,改起来很复杂,且不可上传本地的css文件覆盖,因为微信官方出于安全考虑,只能上传公网文件,或者根据herf参数传入。我使用的方法是herf传输传入。
3、herf参数传入应该为经过base64在线编码后的代码,使用css写法无法写入该地方。
4、二维码注意细节:(1)获取二维码并设置回调地址(必须与微信回调域一致,否则二维码会报错)(2)通过回调接口得到授权临时票据code(3)通过临时票据调用微信接口获取access_token、openid(用户微信唯一标识)(4)通过access_token、openid调用微信接口获取用户信息(5)完成注册登录业务。

效果图如下:


部分核心代码:
(1)获取微信openID工具类
主要作用调微信的API


package com.xk.wechatlogin.util;

/**
 * @version : 1.0
 * @Author : WuShiWen
 */

import cn.hutool.core.util.ArrayUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.http.HttpUtil;

import java.util.Map;

/**
 * description: WeChatUtils 微信获取用户工具类<br>
 *
 * @date: 2021/8/19 0019 上午 10:05 <br>
 * @author: William <br>
 * version: 1.0 <br>
 */
public class WeChatUtils {

    /**
     * 获取微信accessToken路径
     */
    private static final String GET_ACCESS_TOKEN_URL = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=APPID&secret=SECRET&code=CODE&grant_type=authorization_code";

    /**
     * 微信appId
     */
    private static final String APP_ID = "wxa5fb23212134f3af7";

    /**
     * 微信appSecret
     */
    private static final String APP_SECRET = "ad32346645fffsdff643434067105f755f";


    /**
     * description: getAccessToken  根据code获取accessToken<br>
     * version: 1.0 <br>
     * @date: 2021/8/19 0019 上午 10:10 <br>
     * @author: William <br>
     * @param code   微信用户授权code
     * @return java.util.Map<java.lang.String,java.lang.String>
     */
    public static Map<String,String> getAccessToken(String code){
        return getAccessToken(code,APP_ID,APP_SECRET);
    }

    /**
     * description: getAccessToken 根据code获取微信用户信息,返回map如果正确map包含access_token ,如果错误则包含:errcode<br>
     * version: 1.0 <br>
     * @date: 2021/8/19 0019 上午 10:11 <br>
     * @author: William <br>
     * @param code       微信授权code
     * @param appId      微信appId
     * @param appSecret  微信appSecret
     * @return java.util.Map<java.lang.String,java.lang.String>
     */
    public static Map<String,String> getAccessToken(String code,String appId,String appSecret){
        //判断所有字段不能为空
        if(isAnyBlank(code,appId,appSecret)){
            throw new IllegalArgumentException("参数错误");
        }
        String requestUrl = GET_ACCESS_TOKEN_URL.replace("APPID",appId)
                .replace("SECRET",appSecret).replace("CODE",code);
        String result = HttpUtil.get(requestUrl);
        return JsonUtils.parseMap(result, String.class, String.class);
    }

    /**
     * description: isAnyBlank 判断是否存在空字符串,Hutool未编写<br>
     * version: 1.0 <br>
     * @date: 2021/8/19 0019 上午 10:25 <br>
     * @author: William <br>
     * @param strs   字符串
     * @return java.lang.Boolean
     */
    public static Boolean isAnyBlank(CharSequence... strs){
        //如果为空直接返回true
        if (ArrayUtil.isEmpty(strs)) {
            return true;
        }
        for (CharSequence str : strs) {
            if (StrUtil.isBlank(str)) {
                return true;
            }
        }
        return false;
    }

}


jsonutils作用解析json字符串
也可以使用JSON解析库来解析JSON数据,如:org.json、Gson、Jackson等


package com.xk.wechatlogin.util;

/**
 * @version : 1.0
 * @Author : WuShiWen
 */
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.util.List;
import java.util.Map;

/**
 * description: json工具类 <br>
 * version: 1.0 <br>
 * @date: 2019/7/20 0019 上午 10:17 <br>
 * @author: William <br>
 */
public class JsonUtils {

    public static final ObjectMapper MAPPER = new ObjectMapper();

    private static final Logger logger = LoggerFactory.getLogger(JsonUtils.class);

    public static String serialize(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj.getClass() == String.class) {
            return (String) obj;
        }
        try {
            return MAPPER.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            logger.error("json序列化出错:" + obj, e);
            return null;
        }
    }

    public static <T> T parse(String json, Class<T> tClass) {
        try {
            return MAPPER.readValue(json, tClass);
        } catch (IOException e) {
            logger.error("json解析出错:" + json, e);
            return null;
        }
    }

    public static <E> List<E> parseList(String json, Class<E> eClass) {
        try {
            return MAPPER.readValue(json, MAPPER.getTypeFactory().constructCollectionType(List.class, eClass));
        } catch (IOException e) {
            logger.error("json解析出错:" + json, e);
            return null;
        }
    }

    public static <K, V> Map<K, V> parseMap(String json, Class<K> kClass, Class<V> vClass) {
        try {
            return MAPPER.readValue(json, MAPPER.getTypeFactory().constructMapType(Map.class, kClass, vClass));
        } catch (IOException e) {
            logger.error("json解析出错:" + json, e);
            return null;
        }
    }

    public static <T> T nativeRead(String json, TypeReference<T> type) {
        try {
            return MAPPER.readValue(json, type);
        } catch (IOException e) {
            logger.error("json解析出错:" + json, e);
            return null;
        }
    }

}


企业微信解析openID工具类

package com.xk.wechatlogin.util;

/**
 * @version : 1.0
 * @Author : WuShiWen
 */

import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;

/**
 * description: WeChatUtils 微信获取用户工具类<br>
 *
 * @date: 2021/8/19 0019 上午 10:05 <br>
 * @author: William <br>
 * version: 1.0 <br>
 */
public class QYWeChatUtils {
    public static String getAccessToken() {
        String appId = "ww3122222222101a";//appid企业ID
        String secret = "5e22222222ushkj2234lhgrncqSZ0QtLFDdo";//secret为PC门户扫码登录测试的secret,后续根据实际应用secret修改
        String url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid=" + appId + "&corpsecret=" + secret;//企业微信提供的API接口,不可修改
        try {
            URL obj = new URL(url);
            HttpURLConnection con = (HttpURLConnection) obj.openConnection();
            con.setRequestMethod("GET");

            int responseCode = con.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
                String inputLine;
                StringBuilder content = new StringBuilder();
                while ((inputLine = in.readLine()) != null) {
                    content.append(inputLine);
                }
                in.close();
                System.out.println("content====="+content.toString());
                // 解析返回的JSON数据,提取access_token
                String jsonResponse = content.toString();
                System.out.println("jsonResponse====="+jsonResponse);
                // 这里需要使用JSON解析库来解析JSON数据,如:org.json、Gson、Jackson等
                String accessToken = parseAccessToken(jsonResponse);
                return accessToken;
            } else {
                System.out.println("HTTP request failed. Response Code: " + responseCode);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static String parseAccessToken(String jsonResponse) {
        // 在这里使用JSON解析库来解析JSON数据并提取出access_token的值
        // 例如,使用org.json库
        JSONObject jsonObject = new JSONObject(jsonResponse);
        String accessToken = jsonObject.getString("access_token");
        return accessToken;
    }

    public static String getOpenId(String accessToken, String code) {
        String url = "https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo?access_token=" + accessToken + "&code=" + code;

        try {
            URL obj = new URL(url);
            HttpURLConnection con = (HttpURLConnection) obj.openConnection();
            con.setRequestMethod("GET");

            int responseCode = con.getResponseCode();
            if (responseCode == HttpURLConnection.HTTP_OK) {
                BufferedReader in = new BufferedReader(new InputStreamReader(con.getInputStream()));
                String inputLine;
                StringBuilder content = new StringBuilder();
                while ((inputLine = in.readLine()) != null) {
                    content.append(inputLine);
                }
                in.close();

                // 解析返回的JSON数据,提取openID
                String jsonResponse = content.toString();
                // 这里需要使用JSON解析库来解析JSON数据,如:org.json、Gson、Jackson等
                String openId = parseOpenId(jsonResponse);
                return openId;
            } else {
                System.out.println("HTTP request failed. Response Code: " + responseCode);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }

    public static String parseOpenId(String jsonResponse) {
        // 在这里使用JSON解析库来解析JSON数据并提取出openID的值
        // 例如,使用org.json库
        JSONObject jsonObject = new JSONObject(jsonResponse);
        String openId = jsonObject.getString("UserId");
        return openId;
    }
}


二维码的HTML代码:

<script>
    function weChatLogin() {
        // 创建微信登录的对象
        new WxLogin({
            self_redirect: false, // 是否在iframe内跳转 redirect_uri
            id: 'code', // 希望二维码嵌入容器的 id
            appid: 'wx1111111dd734f3af7',
            scope: 'snsapi_login',//应用授权作用域,拥有多个作用域用逗号(,)分隔,网页应用目前仅填写snsapi_login即可
            redirect_uri: encodeURIComponent("http://127.0.0.1:9019/wechatlogin"),
            //如果引入外部css链接,微信处于安全考虑必须引入公网的链接,或者下面这种写法,通过base64在线编辑后引入
            href: `data:text/css;base64,Lmlt.........`//此出根据实际样式经过base64编码后填入,前缀不要改
        })
    }
</script>
<script>
    //授权回调域:192.168.3.151
    //appid (企业ID)企业微信应用的唯一标识符,用于区分不同的企业微信应用,是用于区分不同的企业微信应用.
    //agentid (应用ID)是企业微信应用的一个属性,是用于区分同一个企业中的不同应用。
    function qyWeChatLogin(){
    window.WwLogin({
        "id" : "code2",  //显示二维码的容器id
        "appid" : "ww35111111312a",
        "agentid" : "1111111",  //企业微信的cropID,在 企业微信管理端->我的企业 中查看
        "redirect_uri" :"http://127.0.0.1:9019/QYWechatlogin",   //重定向地址,需要进行UrlEncode
        "state" : "3828293919281",   //用于保持请求和回调的状态,授权请求后原样带回给企业。该参数可用于防止csrf攻击(跨站请求伪造攻击),建议企业带上该参数
        "href" : `data:text/css;base64,Lmlt...........`//此出根据实际样式经过base64编码后填入,前缀不要改
    });}
</script>


截取url中的参数
 

​
function getQueryString(name) {
        var reg = new RegExp("(^|&)" + encodeURIComponent(name) + "=([^&]*)(&|$)", "i");
        var r = window.location.search.substr(1).match(reg);
        if (r !== null) {
            return decodeURIComponent(r[2]);
        }
        return null;
    }

    // 调用方法
    console.log("userid",getQueryString( "userId" ))
    // alert(getQueryString( "userid" ));
    // alert(getQueryString( "password" ));
    $("#username").val(getQueryString( "userId" ));
    $("#password").val(getQueryString( "password"));
    if($("#username").val()!==""&&$("#username").val()!==null){
        $("#fm1").submit();
    }

​

猜你喜欢

转载自blog.csdn.net/qq_65642052/article/details/131470196