关于java:Spring-Security整合企业微信的扫码登录企微的API惊讶到我了

3次阅读

共计 3821 个字符,预计需要花费 10 分钟才能阅读完成。

本文代码: https://gitee.com/felord/spri…

当初很多企业都接入了企业微信,作为私域社群工具,企业微信凋谢了很多 API,能够买通很多自有的利用。既然是利用,那必定须要做登录。正好企业微信提供了企业微信扫码受权登录性能,而且号称应用了 OAuth,正好拿这个测验一下Spring Security OAuth2 专栏 的威力。

正当我兴高采烈打开文档学习的时候,脸上笑容逐步隐没,这确定是 OAuth 的吗?

参数都变了,跟 OAuth(不论是 1.0 还是 2.0)规定不一样,然而这还不是最离谱的。按失常 OAuth2 的要求,拿到 code 之后就能够换 access_token 了是吧?企业微信的 access_token 竟然和下面扫码获取 code 这一步齐全无关,甚至获取 access_token 才是第一步!

而且这个 access_token 接口,你还不能频繁调用,要缓存起来专用。

那费了半天劲儿去拿 code 有啥用呢?

竟然这个 code 是拿用户信息的,不得不说,我服了!OAuth2 的 123 流程被整成了 213。这也就算了,命名上能不能走点心,一会儿下划线,一会儿驼峰:

{
   "errcode": 0,
   "errmsg": "ok",
   "OpenId":"OPENID",
   "DeviceId":"DEVICEID",
   "external_userid":"EXTERNAL_USERID"
}

这个 JSON 格调,果然是大厂,考究!一个 JSON 要三个人来写才体面!反序列化的时候我还得给你写一个兼容,这是要拉满我的 KPI 是吧?算了,忍忍吧,老板就要这个性能,它就是一坨翔,做开发的也得含泪吃上来,干!

环境筹备

筹备一个内网穿透

开发微信相干的利用都须要搞一个内网穿透,在我往期的文章都有介绍。搞一个映射域名进去,就像上面这样:

http://invybj.natappfree.cc -> 127.0.0.1:8082 

invybj.natappfree.cc会映射到我本地的 8082 端口,也就是我本地要开发利用的端口。

创立利用

首先去 企业微信治理后盾 创立一个利用,如图:

图里的参数 AgentIdSecret要记下来备用。

还有一个企业微信的corpid,你能够从上面这个地位拿到,也要记下来备用。

配置内网穿透域名

创立利用 这一页往下拉到页面底端,你会看到:

点击 已启用 进入上面这个页面:

这里配置你 受权登录利用 生产的正式域名或者下面内网穿透的域名,留神只配置域名,而且不能应用localhost

其实我感觉改写 hosts 文件也能用啊,你能够试一试。

到这里环境就搞定了,接下来就开始写 Spring Security 兼容代码吧。

Spring Security 兼容企业微信扫码登录

写起来太恶心了,不过比照文档和 OAuth2 的流程之后其实也没那么麻烦。我先放出我调试好的配置:

spring:
  security:
    oauth2:
      client:
        registration:
          work-wechat-scan:
            # client-id 为企业微信 的企业 ID
            # 上面 client-id 是假的,你用你本人的企业 ID
            client-id: wwaxxxxxx
            # client-secret 企业微信对应利用的 secret,# 每个企业微信利用都有独立的 secret,不要搞错
            # 上面 client-secret 假的,你用你本人创立的企业微信利用 secret
            client-secret:  nvzGI4Alp3zxxxxxxxKbnfTEets5W8
            authorization-grant-type: authorization_code
            redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
        provider:
          work-wechat-scan:
            authorization-uri: https://open.work.weixin.qq.com/wwopen/sso/qrConnect
            token-uri: https://qyapi.weixin.qq.com/cgi-bin/gettoken
            user-info-uri: https://qyapi.weixin.qq.com/cgi-bin/user/getuserinfo

这里 client-id 应用你企业微信的 企业 IDclient-secret应用下面创立利用的 secret 值。

这里的 work-wechat-scan 是客户端的registrationId

封装企业微信拉起二维码 URL

咱们冀望的是放弃 Spring Security OAuth2 的格调,当我拜访:

http://invybj.natappfree.cc/oauth2/authorization/work-wechat-scan

会重定向到企业微信扫码登录链接,格局为:

https://open.work.weixin.qq.com/wwopen/sso/qrConnect?appid=CORPID&agentid=AGENTID&redirect_uri=REDIRECT_URI&state=STATE

这个和以前胖哥实现微信网页受权的原理差不多,都是通过革新 OAuth2AuthorizationRequestResolver 接口来实现,只须要实现一个 Consumer<OAuth2AuthorizationRequest.Builder> 就行了。

逻辑是:client_id 替换为 appid,减少一个agentid 参数,连带 redirect_uristate四个参数之外的其它 OAuth2 参数全干掉,拼接成下面的URL

这么写:

把这个 Consumer 配置到 DefaultOAuth2AuthorizationRequestResolver 就行了。

适配 OAuth2 获取 access_token

通过这一步扫码拿到 code 就不成问题了,依照 OAuth2 该拿 access_token 了,须要自定义一个函数式接口:

Converter<OAuth2AuthorizationCodeGrantRequest, RequestEntity<?>>

也就是利用 OAuth2AuthorizationCodeGrantRequest 生成 RestTemplate 须要的申请对象 RequestEntity<?>。依照企业微信获取access_token 的文档,这样自定义:

把这个配置到 DefaultAuthorizationCodeTokenResponseClient 就行了。

access_token的缓存,我放在了下一步进行解决。

适配获取用户信息

codeaccess_token 都拿到了,最初一步获取用户的信息。这里是比拟麻烦的因为获取 access_token 后并没有间接提供将 code 传递给 OAuth2UserService 的办法。最初发现 OAuth2AccessTokenResponseadditionalParameters属性能够传递到 OAuth2UserService,于是就利用代理模式革新了OAuth2AccessTokenResponseClient 来实现:

自定义企业微信 OAuth2UserService

这个和微信网页受权我封装的差不多,改下参数封装成 URI 交给 RestTemplate 申请企业微信 API。恶心的是要反序列化兼容三个微信研发工程师写的一个JSON

@Data
public class WorkWechatOAuth2User implements OAuth2User {
    private Set<GrantedAuthority> authorities;
    private Integer errcode;
    private String errmsg;
    @JsonAlias("OpenId")
    private String openId;
    @JsonAlias("UserId")
    private String userId;
}

收尾

拿到用户信息后,就完结了,你实现一个 AuthenticationSuccessHandler 来保障登录凭证和你平台统一,无论是 cookie 还是JWT,最初把它配置到这里:

httpSecurity.oauth2Login()
    .successHandler(AuthenticationSuccessHandler successHandler)

试一下成果

务必应用域名进行拜访,不要应用 localhost 或者IP

拜访 http://invybj.natappfree.cc/login 这里是内网穿透域名,呈现:

企业微信扫码登录的地址其实就是http://invybj.natappfree.cc/oauth2/authorization/work-wechat-scan。点击跳转到扫码页面:

而后用你对应的 企业微信 APP 扫码 企业和用户要和申请利用的统一。扫码后:

这个就是 Spring Security 封装的用户认证信息 Authentication 对象,是真正的登录,这里我没有注入权限,你须要在企业微信的 OAuth2UserService 实现中注入权限和更多的信息。

总结

没有实现不了的,只有把原理和流程搞清楚就行。不过如果上游微信把代码写标准一些,上游何必写这么多冗余的代码。

关注公众号:Felordcn 获取更多资讯

集体博客:https://felord.cn

正文完
 0