https://blog.csdn.net/q610376681/article/details/86546935
我们访问时候出现如下错误:
在之前的第三步,返回Client并携带授权码,返回的Client的地址就是就是现在的redirect地址,地址是如何确定的呢,就是我们在QQ互联上注册时要填写一个回调域,回调域只要配置一个域名就可以了.
我们现在的回调域是下图,我们现在的回调域是有问题的,回调域只要填写域名就可以了,比如365.com,我们传过去的uri是下图,我们访问的地址与服务器跳转回来的地址都应该是登陆时填写的地址.即/auth/qq,那我们现在的uri是localhost,实际回调的是365.com,我们现在要做的就是让redirect参数和rederect地址保持一致.
现在我们将365.com映射到了本机地址,但是它访问的是80端口,因为安全的原因,80端口被禁用了,所有访问80端口的都会跳到9090端口,所以在application.properties中做如下配置.
结果就是当访问www.pinzhi365.com,就会访问本机的localhost:9090端口.
#### 1.2 地址问题
现在我们的地址是/auth/qq,如何改变呢?
我们之前配过SpringSocialConfigure,并将它注了进去
我们之前在spring-security-core里面配置过过SpringSocialConfigure
在spring-security-web里面注入了:
我们查看SpringSocialConfigurer代码,里面有一个configure方法,此方法是new了一个SocialAuthenticationFilter,然后将其加入到过滤器前的AbstractPreAuthenticatedProcessingFilter前面,加入到之前执行了postProcess方法:
protected <T> T postProcess(T object) { return this.objectPostProcessor.postProcess(object); }
addFilterBefore((Filter)this.postProcess(filter), AbstractPreAuthenticatedProcessingFilter.class);
我们现在要做的是继承SpringSocialConfigurer,把方法:postProcess覆盖掉:
public class MySpringSocialConfigurer extends SpringSocialConfigurer { private String filterProcessesUrl; public MySpringSocialConfigurer(String filterProcessesUrl){ this.filterProcessesUrl = filterProcessesUrl; } @Override protected <T> T postProcess(T object) { /** * 1.我们覆盖SpringSocialConfigurer的postProcess * 2.里面的object就是我们之前:SocialAuthenticationFilter */ //1.获取父类处理的结果 SocialAuthenticationFilter filter = (SocialAuthenticationFilter)super.postProcess(object); //2.设置FilterProcessesUrl,由于我们每个应用传递的FilterProcessesUrl可能是不一样的,所以我们将其作为可配置的 filter.setFilterProcessesUrl(filterProcessesUrl); return super.postProcess(object); } }
然后我们在SocialConfig里面配置成我们自己定义的类
SecurityProperties属性为:
public class SocialProperties { /** * SocialAuthenticationFilter的默认过滤器url是:/auth */ private String filterProcessesUrl="/auth"; private QQProperties qq = new QQProperties(); //setter getter }
然后我们第三方应用配置文件去配置application.yml:
yxm: security: social: filterProcessesUrl: /qqLogin qq: app-id: xxx app-secret: xxxx providerId: callback.do
然后我们去前端配置(现在我们更改了配置filterProcessUrl为申请应用的后缀:/qqLogin):
<h3>社交登录</h3> <a href="/qqLogin/callback.do">QQ登录</a>
所以以上地址也是第三步骤中引导客户访问的跳转地址:/qqLogin/callback.do 和qq互联的配置地址是一致的。 用户授权完跳回来也是在这个地址上。
跳进去之后:
提示没有认证:看下请求的日志:
因为默认情况下,我们是没有配置:sigin拦截请求的
我们先看下spring social执行第三方登录时候的代码:主要接口、实现类、以及调用顺序图:
蓝色的都是系统实现的,橘色的是我们自己写的
上面出现问题也是因为:在我们的授权蓝色模块出现问题,signin没有请求拦截到:也就是OAuth2AuthenticationService问题。我们追踪下代码:
判断有没有授权码,如果没有就抛出异常.如果有就拿授权码去换令牌.通过打断点我们发现是换令牌的过程中出现了异常.
public SocialAuthenticationToken getAuthToken(HttpServletRequest request, HttpServletResponse response) throws SocialAuthenticationRedirectException { String code = request.getParameter("code"); //第3步和第4步骤都是会走此逻辑/qqLogin/callback.do;我们根据是否有授权码来判断是第3步还是第4步。 if (!StringUtils.hasText(code)) {//有授权码:说明是第四步:此时我们会去操作连接工厂 OAuth2Parameters params = new OAuth2Parameters(); params.setRedirectUri(this.buildReturnToUrl(request)); this.setScope(request, params); params.add("state", this.generateState(this.connectionFactory, request)); this.addCustomParameters(params); throw new SocialAuthenticationRedirectException(this.getConnectionFactory().getOAuthOperations().buildAuthenticateUrl(params)); } else if (StringUtils.hasText(code)) {//没有授权码:说明是第3步:此时我们会调用服务提供商的getOAuthOperations()的exchangeForAccess try { String returnToUrl = this.buildReturnToUrl(request); AccessGrant accessGrant = this.getConnectionFactory().getOAuthOperations().exchangeForAccess(code, returnToUrl, (MultiValueMap)null); Connection<S> connection = this.getConnectionFactory().createConnection(accessGrant); return new SocialAuthenticationToken(connection, (Map)null); } catch (RestClientException var7) { this.logger.debug("failed to exchange for access", var7); return null; } } else { return null; } }
this.getConnectionFactory().getOAuthOperations().exchangeForAccess(code, returnToUrl, (MultiValueMap)null)
上面会通过OAuth2Template调用: