1。前言本来打算讲解一下SpringSecurity中OAuth2.0的机制,并使用小程序登录来练习,结果发现小程序登录过程和SpringSecurity中OAuth2.0的登录过程有点不一样,所以全部推翻了我写了很长时间的东西。然而过了一天,突然又觉得好了。让我们一起试试吧。2、小程序登录流程分析小程序的登录流程是这样的:微信小程序登录时序图SpringSecurity中的OAuth2.0Code模式是这样的:SpringSecurityOAuth2.0Code模式时序图从这两张图中可以看出与上面最大的区别是微信小程序中获取代码不需要通过后台服务器调用,而在SpringSecurity中需要调用(步骤一、步骤二、步骤三)。腾讯应该也借鉴了OAuth2.0,只是做了一些改动。这就是让我放弃的区别。谁能想到解决办法?如果小程序已经持有代码,还需要将代码传递给后端服务器执行后续流程。那么我们是否可以使用图2中调用redirectUri的第三步呢?换个角度看问题,第三方就是小程序。无论如何,它也将一个代码传递给后端服务器。只需返回登录状态即可。反正,剩下的登录过程和小程序无关。我觉得还可以。在SpringSecurity中,我们可以使用代码通过tokenUri交换token。那么在微信小程序登录过程中,代码最终交换的只是登录状态,并没有具体的要求。但是后台肯定需要获取用户的一些信息,比如openId,用户微信信息之类的。总之,必须按照微信平台提供的API来实现。这可以通过转换tokenUri和userInfoUri来完成。3.各种猜想借用思路没有错,自己也实现了,但是改造成本太高,写了一大堆兼容的代码。如果不深入SpringSecurity,很难做到这一点,也不容易理解。为了简化实现,我决定借鉴SpringSecurity中OAuth2.0的思想。Filter拦截小程序的登录URL,然后通过RestTemplate向微信服务器执行请求获取结果,处理后返回登录状态。时序图如下:小程序登录开发时序图对应的伪代码实现:packagecn.felord.spring.security.filter;importorg.springframework.http.ResponseEntity;importorg.springframework.security.web.util.matcher.AntPathRequestMatcher;导入组织。springframework.security.web.util.matcher.RequestMatcher;importorg.springframework.util.Assert;importorg.springframework.util.LinkedMultiValueMap;importorg.springframework.util.MultiValueMap;importorg.springframework.web.client.RestTemplate;importorg.springframeweb.filter.OncePerRequestFilter;importorg.springframework.web.util.UriComponentsBuilder;importjavax.servlet.FilterChain;importjavax.servlet.ServletException;importjavax.servlet.http.HttpServletRequest;importjavax.servlet.http.HttpServletResponse.Exportimportjava.net.URI;/***小程序登录过滤器**@authorfelord.cn*@since1.0.4.RELEASE*/publicclassWeChatAppLoginFilterextendsOncePerRequestFilter{privatefinalRequestMatcherrequiresAuthenticationRequestMatcher;privatefinalRestTemplaterestTemplate;privateStringappId;privateStringsecret;privatestaticfinalStringWX_URL="https://api.weixin.qq.com/sns/jscode2session";publicWeChatAppLoginFilter(StringloginProcessingUrl,StringappId,Stringsecret){this.appId=appId;this.secret=secret;Assert.notNull(loginProcessingUrl,"loginProcessingUrlmustnotbenull");this.requiresAuthenticationRequestMatcher=newAntPathRequestMatcher(loginProcessingUrl,"POST");this.restTemplate=newRestTemplate();}@OverrideprotectedvoiddoFilterInternal(HttpServletRequestrequest,HttpServletResponseresponse,FilterChainfilterChain)throwsServletException,IOException{//拦截微信登录if(requiresAuthenticationRequestMatcher.matches(request)){//todo从请求中获取code参数。这里的逻辑是根据你的情况来实现的。StringjsCode="你可以自己从请求中获取";//做必要的校验写MultiValueMap