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中并返回。

如果你想在Java实习中实现企业微信自建应用授权登录获取用户信息,可以按照以下步骤进行: 1. 获取应用ID和应用Secret,可以在企业微信管理后台创建自建应用时获得。 2. 配置可信域名、回调URL、授权回调域名和网页授权域名,确保域名的正确性和安全性。 3. 在Java项目中使用企业微信提供的OAuth2.0接口或者开源的Java SDK,实现授权登录功能。 4. 引导用户跳转到企业微信授权页面进行授权授权成功后,企业微信会回调预设的回调URL,返回授权码。 5. 通过授权码获取access_token和用户信息,可以使用企业微信提供的OAuth2.0接口或者开源的Java SDK完成。 以下是一个使用Java SDK实现企业微信自建应用授权登录获取用户信息的示例代码: ```java // 1. 获取应用ID和应用Secret String appId = "your_app_id"; String appSecret = "your_app_secret"; // 2. 配置可信域名、回调URL、授权回调域名和网页授权域名 // 3. 使用Java SDK实现授权登录功能 WxCpService wxCpService = WxCpConfiguration.getCpService(appId); String redirectUrl = "https://your_callback_url"; String state = "your_state"; String authorizeUrl = wxCpService.getOauth2Service().buildAuthorizationUrl(redirectUrl, state); // 4. 引导用户跳转到企业微信授权页面进行授权 // 5. 企业微信回调预设的回调URL,返回授权码 String code = request.getParameter("code"); // 6. 通过授权码获取access_token和用户信息 WxCpOAuth2AccessToken wxCpOAuth2AccessToken = wxCpService.getOauth2Service().getAccessToken(code); String accessToken = wxCpOAuth2AccessToken.getAccessToken(); String userId = wxCpOAuth2AccessToken.getUserId(); WxCpUser wxCpUser = wxCpService.getUserService().getById(userId); ``` 注意事项: 1. 在开发过程中,需要保证应用ID、应用Secret、回调URL等参数的正确性。 2. 在获取access_token和用户信息时,需要保证请求的准确性和安全性。 3. 在获取用户信息时,需要保证授权作用域的正确性和权限的足够性。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值