环境:springboot2.3.10.RELEASE + OAuth2 请先阅读《SpringBoot2 整合OAuth2实现统一认证 》文章,本篇内容是调用之前写的一个OAuth2认证服务。 说明: authorization-uri:你的认证服务地址 DEFAULT_FILTER_PROCESSES_URI:默认该过滤器能处理的请求地址。该过滤器的作用就是获取token信息然后交由AuthenticationManager以登录最终用户。 这里设置了下session,因为不设置在跟踪源码的时候你会发现session始终为空 到此配置就完成了,接下来进行测试。 访问测试接口/home 登录后出现如下错误信息 这个错误的原因就是从session中无法获取OAuth2AuthorizationRequest保存的对象。 OAuth2LoginAuthenticationFilter.java 跟踪源码查看问题出在哪里? 进入OAuth2LoginAuthenticationFilter类 进入选中的方法中 注意这里的 这行代码是从session中获取跳转前保存在session中的OAuth2AuthorizationRequest对象,没有被获取 在整个处理流中并不能从session中获取信息OAuth2AuthorizationRequest信息。那这个对象又是在哪里设置的呢?是由另外一个核心Filter处理的OAuth2AuthorizationRequestRedirectFilter。 注意:这里有两次的重定向,首次这里的if肯定是不会进入的,因为该过滤器默认处理的请求地址是/oauth2/authorization 第一次重定向: 接着OAuth2AuthorizationRequestRedirectFilter就能处理该请求,并且进入if语句中进行重定向到认证服务。而设置保存OAuth2AuthorizationRequest对象到session中就在如下方法中。 设置和获取使用的key都是同一个(确保没有错误) 测试session是否真的有东西?我把跳转到认证服务的地址改错,然后请求,接着用另外一个接口打印session中的内容。 session中是有内容的,接着吧跳转地址改对,再看session中的内容 跳转到登录页面后,不进行登录,接着访问打印session的接口: session中已经没有内容了。 证实:session是跳转到了认证服务后就没有了。难道真的是stackoverflow上所说? 翻译过来就是: 这些错误意味着找不到授权请求.授权请求存储在会话中,因此有些会话未被存储.默认情况下,会话由cookie管理. 最后来个结果图,能够返回code,有了这个就可以获取token,获取了token就可以获取用户信息,然后将用户信息交由AuthenticationManager管理实现登录。 在c:\windows\System32\drivers\etc\host文件中添加了如下 让我们的认证服务通过这个域名访问,修改应用配置文件: 都修改域名形式,这样我们的cookie应该不会被替换了。接下来再次测试,果然成功了。这里的处理流程是:获取token,获取token后调用获取用户信息接口。 1、自动调用获取token的接口 OAuth2LoginAuthenticationProvider.java 2、通过上一步获取的token再自动调用获取用户信息表 注意:获取用户信息的接口,你应该只验证token是否合法即可,不要用security再进行拦截了。security应该排除这个接口。接口如下: 整合第三方OAuth2的核心过滤器: OAuth2AuthorizationRequestRedirectFilter.java 完毕!!! 给个关注吧谢谢 SpringBoot2 整合 OAuth2 资源认证(保护)相关依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
应用配置
server:
servlet:
session:
timeout: 30m
---
spring:
security:
oauth2:
client:
provider:
xgpack:
authorization-uri: http://localhost:8208/oauth/authorize
token-uri: http://localhost:8208/oauth/token
user-info-uri: http://localhost:8208/users/userinfo
user-name-attribute: name
registration:
auth2:
provider: xgpack
client-id: 1
client-secret: 1
authorization-grant-type: authorization_code
redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
---
logging:
level:
org.springframework.security: debug
token-uri:获取token地址
user-info-uri:获取用户信息地址
user-name-attribute:用户名,在获取用户信息接口返回的json中的key
redirect-uri:跳转地址,这个地址必须与服务认证那里配置的跳转地址一致。{baseUrl}系统会自动替换你当前服务的地址及端口,{registrationId} 会被替换成auth2。默认情况下系统只能处理/login/oauth2/code/* 地址,当登录成功后跳转回来这个地址时由OAuth2LoginAuthenticationFilter过滤器进行处理。部分源码如下:public class OAuth2LoginAuthenticationFilter extends AbstractAuthenticationProcessingFilter {
public static final String DEFAULT_FILTER_PROCESSES_URI = "/login/oauth2/code/*";
private static final String AUTHORIZATION_REQUEST_NOT_FOUND_ERROR_CODE = "authorization_request_not_found";
private static final String CLIENT_REGISTRATION_NOT_FOUND_ERROR_CODE = "client_registration_not_found";
private ClientRegistrationRepository clientRegistrationRepository;
private OAuth2AuthorizedClientRepository authorizedClientRepository;
private AuthorizationRequestRepository<OAuth2AuthorizationRequest> authorizationRequestRepository =
new HttpSessionOAuth2AuthorizationRequestRepository();
public OAuth2LoginAuthenticationFilter(ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService authorizedClientService) {
this(clientRegistrationRepository, authorizedClientService, DEFAULT_FILTER_PROCESSES_URI);
}
// ....
}
Security配置
@Configuration
public class OAuthConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable() ;
http.authorizeRequests()
.antMatchers("/error", "/webjars/**", "/resources/**", "/index/**").permitAll()
.anyRequest().authenticated()
.and()
.oauth2Login()
.logout();
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.ALWAYS);
}
}
Map<String, OAuth2AuthorizationRequest> authorizationRequests = session == null ? null : (Map<String, OAuth2AuthorizationRequest>) session.getAttribute(this.sessionAttributeName);
public class OAuth2AuthorizationRequestRedirectFilter extends OncePerRequestFilter {
public static final String DEFAULT_AUTHORIZATION_REQUEST_BASE_URI = "/oauth2/authorization";
}
this.sendRedirectForAuthorization(request, response, authorizationRequest);
所以我认为这可能是因为你在localhost上运行了所有东西,所以第一个cookie由localhost:8080设置来存储授权请求会话数据,&当你登录到localhost:8081时,它会为它的会话设置另一个cookie。(这里经查,cookie同ip不同端口,cookie共享)。解决上面的问题
spring:
security:
oauth2:
client:
provider:
xgpack:
authorization-uri: http://www.xg.com:8208/oauth/authorize
token-uri: http://www.xg.com:8208/oauth/token
user-info-uri: http://www.xg.com:8208/users/userinfo
user-name-attribute: name
registration:
auth2:
provider: xgpack
client-id: 1
client-secret: 1
authorization-grant-type: authorization_code
redirect-uri: '{baseUrl}/login/oauth2/code/{registrationId}'
@GetMapping("/userinfo")
public Map<String, Object> userinfo(){
Map<String, Object> res = new HashMap<>() ;
String token = extractToken() ;
OAuth2Authentication auth = tokenService.loadAuthentication(token) ;
res.put("name", auth.getName()) ;
return res ;
}
OAuth2LoginAuthenticationFilter.java