前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Spring Security 实战干货:微信小程序登录与Spring Security结合的思路分享

Spring Security 实战干货:微信小程序登录与Spring Security结合的思路分享

作者头像
码农小胖哥
发布2021-03-19 12:37:37
4.8K2
发布2021-03-19 12:37:37
举报

关注并星标,文末获取相关学习资料

1. 前言

原本打算把Spring SecurityOAuth2.0的机制讲完后,用小程序登录来实战一下,发现小程序登录流程和Spring SecurityOAuth 2.0登录的流程有点不一样,就把写了半天的东西全部推翻了。但是,但是过了一天之后,突然感觉又可以了。我们来一起试一试。

2. 小程序登录流程分析

小程序的登录流程是这样的:

微信小程序登录时序图

而在Spring Security中的OAuth 2.0 Code模式是这样的:

Spring Security OAuth2.0 Code模式时序图

从这两张图上看最大的差别就是微信小程序中获取code不需要通过后端服务器的调用,而Spring Security中需要(第1步,第2步,第3步)。腾讯应该也是借鉴了OAuth 2.0,但是做了一些改动。

❝让我放弃的也是这个差别,有没有人能想到解决方法呢?

假如说小程序已经持有了code,它依然需要将code传递给后端服务器来执行后面的流程。那么我们能不能利用图2中第3个调用redirectUri的步骤呢?换个角度来看问题第三方就是小程序反正它也是将一个code传递给了后端服务器,只要返回登录状态就行了,反正剩下的登录流程都跟小程序无关。我觉得它是可以的。在Spring Security中我们可以使用code通过tokenUri来换取token。那么在微信小程序登录流程中,code最终换取的只是登录态,没有特定的要求。但是后端肯定需要去获取用户的一些信息,比如openId,用户微信信息之类的。总之要根据微信平台提供的API来实现。通过改造tokenUriuserInfoUri可以做到这一点。

3. 思路借鉴

❝所有的猜想都没有错,而且我也实现了,但是改造成本过高了,写了很多兼容性的代码,如果不深入Spring Security,很难实现这一点,而且也不好理解。

为了简化实现,我决定借鉴Spring SecurityOAuth 2.0的思路。Filter拦截小程序登录URL,然后通过RestTemplate执行向微信服务器请求获取结果,处理后返回登录态。时序图如下:

小程序登录开发时序图

对应的伪代码实现:

代码语言:javascript
复制
package cn.felord.spring.security.filter;

import org.springframework.http.ResponseEntity;
import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
import org.springframework.security.web.util.matcher.RequestMatcher;
import org.springframework.util.Assert;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.UriComponentsBuilder;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.URI;

/**
 * 小程序登录过滤器
 *
 * @author felord.cn
 * @since 1.0.4.RELEASE
 */
public class WeChatAppLoginFilter extends OncePerRequestFilter {

    private final RequestMatcher requiresAuthenticationRequestMatcher;
    private final RestTemplate restTemplate;
    private String appId;
    private String secret;
    private static final String WX_URL = "https://api.weixin.qq.com/sns/jscode2session";

    public WeChatAppLoginFilter(String loginProcessingUrl, String appId, String secret) {
        this.appId = appId;
        this.secret = secret;
        Assert.notNull(loginProcessingUrl, "loginProcessingUrl must not be null");
        this.requiresAuthenticationRequestMatcher = new AntPathRequestMatcher(loginProcessingUrl, "POST");
        this.restTemplate = new RestTemplate();
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {

        // 拦截微信登录
        if (requiresAuthenticationRequestMatcher.matches(request)) {
            //todo 从request中获取 code 参数 这里逻辑根据你的情况自行实现
            String jsCode = "你自行实现从request中获取";
            //todo 必要的校验自己写
            MultiValueMap<String, String> queryParams = new LinkedMultiValueMap<>();
            queryParams.add("appid", this.appId);
            queryParams.add("secret", this.secret);
            queryParams.add("js_code", jsCode);
            queryParams.add("grant_type", "authorization_code");


            URI uri = UriComponentsBuilder.fromHttpUrl(WX_URL)
                    .queryParams(queryParams)
                    .build()
                    .toUri();
            //todo 这里 Object 自行封装为具体对象
            ResponseEntity<Object> result = this.restTemplate.getForEntity(uri, Object.class);

            //todo 处理 result 比如后端存储、后端授权、角色资源处理、注册、对session_key的处理等等你需要的业务逻辑
            // 最后放入HttpServletResponse中返回前端返回

        } else {
            filterChain.doFilter(request, response);
        }
    }
}

最后一定别忘了把过滤器配置到WebSecurityConfigurerAdapterHttpSecurity中去。

4. 总结

本篇讲解了Spring Security和微信小程序登录相结合的思路历程。本来不需要长篇大论OAuth 2.0,之所以写出来是让你明白开发中要善于发现一些相似的东西,通过差异对比来探讨他们结合的可能性,这也是一种自我提升的方法。方法远比结果重要,形成自己的方法论就能富有创造力。关注公众号:码农小胖哥 并设置为星标,回复 2021开工福利 即可获取共计24万字的原创Spring Security入门实战干货资料

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-03-04,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 码农小胖哥 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 前言
  • 2. 小程序登录流程分析
  • 3. 思路借鉴
  • 4. 总结
相关产品与服务
访问管理
访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档