OAuth2客户端:
spring-boot-starter-security:2.1.2.RELEASE
spring-security-oauth2-client:5.1.3.RELEASE
OAuth2认证服务:
spring-security-oauth2-autoconfigure:2.1.2.RELEASE
具体代码就不一一贴出来了,自己下载看,如有操作姿势不对的地方请联系我当面打脸
栗子源码:我是马云(oauth2xxx后缀的两个模块)
以下产生的问题,各位不一定产生,比较笨debug一点点调试出来的,没找到合适的参考资料,官网
问题1:org.springframework.security.oauth2.core.OAuth2AuthenticationException: [authorization_request_not_found]
产生该问题的主要原因本机测试中的授权中心和客户端都是采用localhost主机名,对于浏览器来说同一个域名,导致jsessionId在跳转到授权中心前的值和授权完毕后跳转回来的值不一致,浏览器认为是同一个域名所以JSessionID会被覆盖,导致在客户端从session中获取保存的authorizationRequest时获取不到,authorizcationRequest存放在session的Attribute中,key为JSessionID; 处理该问题方法就是让他们两个处于不同的域名或者ip,可以修改hosts增加一个域名。本文中OAuth2Server直接使用的局域网ip地址也可以解决这个问题,OAuth2Client使用localhost。
问题2:(该问题可能就我遇到了吧,没配置EnableResourceServer)
org.springframework.security.oauth2.core.OAuth2AuthenticationException: [invalid_user_info_response] An error occurred while attempting to retrieve the UserInfo Resource: 401 null
该问题是在OAuth2Client程序获取到授权中心回调的code后调用/oauth/token获取access_token后,紧接着调用userInfoUri获取用户认证信息(restTemplate),此时传递的是头信息包含Authentication: Bearer xxxxxxxx(access_token),但是授权中心获取到该请求后没有使用OAuth2过滤器认证(由于没有配置EnableResourceServer导致该过滤器没被启用), 而是通过session获取认证信息,但是由于没有携带session信息导致返回401未授权错误,出现上述问题。解决方法就是定义EnableResourceServer如下:并且注意下面注释部分的代码说明
package adminlte.config;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
/**
* OAuth2不定义ResourceServer,认证鉴权采用方式为:
* 客户端请求并授权后,oauth2会写一个JSESSIONID到客户端,后续客户端请求只要cookie中
* 有这个会话id即可,oauth2每次收到请求会首先到session中获取授权信息,获取不到则返回401
* ,所以即使携带access_token访问一样会导致401 unauthorized,
* 避免此问题需要启用EnableResourceServer注解,会增加OAuth2AuthenticationProcessingFilter过滤器
* ,该过滤器处理通过access_token访问才会生效
*
* EnableResourceServer注解会启用OAuth2的token认证,在原基础上增加OAuth2AuthenticationProcessingFilter过滤器
* EnableResourceServer->(import ResourceServerConfiguration)->configure(http)->ResourceServerSecurityConfigurer
* -> OAuth2AuthenticationProcessingFilter
* @author *已打码*
*/
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
//此处是关键,默认stateless=true,只支持access_token形式,
// OAuth2客户端连接需要使用session,所以需要设置成false以支持session授权
resources.stateless(false);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated()
.and()
.formLogin()
.and()
.httpBasic();
//需要的时候创建session,支持从session中获取认证信息,ResourceServerConfiguration中
//session创建策略是stateless不使用,这里其覆盖配置可创建session
http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
}
}
OAuth2Server Filter链
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
LogoutFilter
OAuth2AuthenticationProcessingFilter
UsernamePasswordAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
BasicAuthenticationFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]
OAuth2Client Filter链
Security filter chain: [
WebAsyncManagerIntegrationFilter
SecurityContextPersistenceFilter
HeaderWriterFilter
CsrfFilter
LogoutFilter
OAuth2AuthorizationRequestRedirectFilter
OAuth2LoginAuthenticationFilter
DefaultLoginPageGeneratingFilter
DefaultLogoutPageGeneratingFilter
RequestCacheAwareFilter
SecurityContextHolderAwareRequestFilter
AnonymousAuthenticationFilter
SessionManagementFilter
ExceptionTranslationFilter
FilterSecurityInterceptor
]