JAVA-企业微信H5自建应用之OAuth2授权登录

企业微信的签名在之前讲了,这里免密登录直接上代码.

@GetMapping(value = "/oAuth2Url")
public String oAuth2Url(HttpServletRequest request, @RequestParam("url") String url) throws IOException {
        //目前url为前端传,不需要后端做拼接
        String orgId = "企业id";
        String oauth2Url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={CORPID}&redirect_uri={REDIRECTURI}&response_type=code&scope=snsapi_base&state=STATE#wechat_redirect".replace("{CORPID}",orgId).replace("{REDIRECTURI}", url);
        return oauth2Url;
    }

因为这个重定向跳转的地址是固定的,前端拼接还是后端拼接其实都一样,我这边就直接让前端拼好了地址传给我。

但是这里有个大坑,需要注意下:

跳转到他写的重定向地址后,企业微信会返回给他code,前端在跳转后的页面直接调我的下一个接口:用code获取用户信息(code是一次性的)。

@GetMapping(value = { "/oAuth2Check"})
    public Result oAuth2Check(HttpServletRequest request, @RequestParam String code) throws Exception {
        String token = null;
        UserEntity entity = null;
        String refreshToken = null;
        JSONObject json = new JSONObject();
        // 调用获取access_token的接口,默认从缓存中获取
        AccessToken accessToken = getAccessToken();
        if(accessToken.getErrcode() != 0)  return Result.error(accessToken.getErrmsg());
        if (Objects.nonNull(accessToken) && StringUtil.isNotBlank(accessToken.getAccessToken())) {
            // 通过access_token和code,调用获取用户信息的接口
            WXUserResponse wxUser = WeiXinQiYeUtil.getMemberByCode(accessToken.getAccessToken(), code, WeiXinQiYeConstants.AGENTID);
            // 根据手机号校验用户正确性
            entity = userService.getUserListByMobile(wxUser.getMobile(), wxUser.getName());
            //小程序端登录后返回可用权限
            List<MenuEntity> list = menuService.getMenuListByName(entity, "小程序首页");
            List<String> permissionsList = new ArrayList<>();
            if (CollectionUtil.isNotEmpty(list)) {
                list.parallelStream().forEach(e -> permissionsList.add(e.getName()));
            }
            json.put("permissions", permissionsList);
            //授权登录,必须走免密登录
            MyUsernamePasswordToken myUsernamePasswordToken = new MyUsernamePasswordToken(entity.getAccount());
            // 登录不在该处处理,交由shiro处理
            Subject subject = SecurityUtils.getSubject();
            subject.login(myUsernamePasswordToken);
            //生成token并返回
            token = JwtUtils.generateToken(new UserToken(entity.getAccount(), entity.getId().toString(), entity.getName(),null));
            //生成refreshToken
            refreshToken = UUID.randomUUID().replaceAll("-", "");
            //保存refreshToken至redis,使用hash结构保存使用中的token以及用户标识
            String refreshTokenKey = String.format(JwtUtils.REFRESH_TOKEN_KEY_FORMAT, refreshToken);
            String refreshTokenUserKey = String.format(JwtUtils.REFRESH_TOKEN_KEY_FORMAT, entity.getAccount());
            template.opsForHash().put(refreshTokenUserKey,
                    "refreshToken", refreshToken);
            template.opsForHash().put(String.format(JwtUtils.REFRESH_TOKEN_KEY_FORMAT, refreshTokenKey),
                    CommonConstants.TOKEN, token);
            template.opsForHash().put(refreshTokenKey,
                    "userName", entity.getAccount());
            //refreshToken设置过期时间
            template.expire(refreshTokenKey,
                    JwtUtils.TOKEN_EXPIRE_TIME, TimeUnit.MILLISECONDS);
            //用户表TOKEN 等于refreshToken
            entity.setToken(refreshToken);
            entity.setLoserTime(null);
            entity.setLoserNumber(CommonDefinition.LOSER_NUMBER);
            entity.setLoginType(CommonDefinition.LOGIN_TYPE_SUCCEED);
            userService.updateById(entity);
        }
        json.put(CommonConstants.TOKEN, token);
        json.put("refreshTokenKey", refreshToken);
        LoginLog(true, "", entity.getAccount(), request, "0");
        return new Result(ResultCodeEnum.SUCCESS, json);

    }

这里首先通过getAccessToken()获取必要参数access_token。access_token要做缓存,我这里是存在redis中。

 WeiXinQiYeUtil.getMemberByCode(accessToken.getAccessToken(), code, WeiXinQiYeConstants.AGENTID)。这里是通过code去获取用户信息,AGENTID为snsapi-userinfo。

 /**
   * 根据code获取用户信息
   * @param token acess_token
   * @param code 企业微信返回的code
   * @param agentId 查看用户信息范围
*/
public static WXUserResponse getMemberByCode(String token, String code, String agentId){
        WXUserResponse wxUser = null;
        //获取userId
        WXUserResponse result = oAuth2GetUserByCode(token, code, agentId);
        logger.info("result :" + result);
        if (result.getErrcode().equals("0")) {
            if (StringUtils.isNotBlank(result.getUserid())) {
                //拼装获取访问用户身份详细信息的url请求
                String userurl = "https://qyapi.weixin.qq.com/cgi-bin/user/get?access_token={ACCESS_TOKEN}&userid={USERID}".replace("{ACCESS_TOKEN}", token).replace("{USERID}", result.getUserid());
                //获取访问用户身份的详细信息
                String userinfo = HttpUtil.get(userurl);
                if(Objects.nonNull(userinfo)){
                    com.alibaba.fastjson.JSONObject jsonObject = com.alibaba.fastjson.JSONObject.parseObject(userinfo);
                    wxUser = JSON.toJavaObject(jsonObject, WXUserResponse.class);
                }
                return wxUser;
            }
        }
        return result;
    }
/**
     * 获取用户userid
     * @param token
     * @param code
     * @param agentId
     * @return
     */
    public static WXUserResponse oAuth2GetUserByCode(String token, String code, String agentId) {
        WXUserResponse wxUser = new WXUserResponse();
        String menuUrl = WeiXinQiYeConstants.GET_OAUTH2_URL.replace("ACCESS_TOKEN", token).replace("CODE", code).replace("AGENTID", agentId + "");
        String userinfo = HttpUtil.get(menuUrl);
        logger.info("userinfo: " + userinfo);
        JSONObject jsonObject = null;
        if (userinfo != null) {
            try {
                jsonObject = JSONObject.fromObject(userinfo);
                logger.info("jsonObject: " + jsonObject);
                if (jsonObject.getString("UserId") != null && jsonObject.getString("UserId").length() > 0) {
                    wxUser.setErrmsg(jsonObject.getString("errmsg"));
                    wxUser.setErrcode(jsonObject.getString("errcode"));
                    wxUser.setUserid(jsonObject.getString("UserId"));
                } else {
                    wxUser.setErrmsg(jsonObject.getString("errmsg"));
                    wxUser.setErrcode(jsonObject.getString("errcode"));
                }
            } catch (Exception e) {
                wxUser.setErrmsg("accessToken 超时......");
                wxUser.setErrcode("42001");
            }
        }
        return wxUser;
    }

因为自建应用的作用域为snsapi_base。获取的用户信息非常简单,校验用户直接就用姓名和手机号就可以了,继续返回该用户的用户权限信息,并用shiro的免密登录,jwt生成token,缓存在redis中并返回。

您好!对于H5网页微信授权登录,您可以使用Java开发语言来实现。下面是一个简单的示例代码,帮助您理解如何在Java中进行微信授权登录: ```java import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.HttpURLConnection; import java.net.URL; public class WeChatLogin { public static void main(String[] args) throws IOException { // 获取授权登录的code String code = getAuthorizationCode(); // 通过code获取access_token和openid String appId = "your_app_id"; String appSecret = "your_app_secret"; String accessTokenUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid=" + appId + "&secret=" + appSecret + "&code=" + code + "&grant_type=authorization_code"; String accessTokenResponse = sendGetRequest(accessTokenUrl); // 解析access_token和openid String accessToken = parseJsonValue(accessTokenResponse, "access_token"); String openid = parseJsonValue(accessTokenResponse, "openid"); // 使用access_token和openid进行业务逻辑处理 // ... System.out.println("Access Token: " + accessToken); System.out.println("OpenID: " + openid); } private static String getAuthorizationCode() { // 在此处实现获取授权登录的code的逻辑 // ... return "authorization_code"; } private static String sendGetRequest(String url) throws IOException { URL getUrl = new URL(url); HttpURLConnection connection = (HttpURLConnection) getUrl.openConnection(); connection.setRequestMethod("GET"); connection.connect(); BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream())); StringBuilder response = new StringBuilder(); String line; while ((line = reader.readLine()) != null) { response.append(line); } reader.close(); return response.toString(); } private static String parseJsonValue(String json, String key) { // 在此处实现解析JSON中指定key的value的逻辑 // ... return "value"; } } ``` 请注意,这只是一个简单的示例代码,实际实现中您需要根据自己的需求进行修改和完善。另外,您需要替换代码中的`your_app_id`和`your_app_secret`为您在微信开放平台申请的真实App ID和App Secret。 希望这个示例对您有所帮助!如果您有其他问题,请随时提问。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值