Java SpringBoot 1.5.x+;安全+;OAuth2
我有一个带有OAuth2安全性的SpringBootRESTAPI 今天,我已将我的Java SpringBoot 1.5.x+;安全+;OAuth2,java,spring-boot,spring-security,oauth,oauth-2.0,Java,Spring Boot,Spring Security,Oauth,Oauth 2.0,我有一个带有OAuth2安全性的SpringBootRESTAPI 今天,我已将我的spring boot starter父版从1.4.2升级到1.5.2 变化完全把我弄糊涂了 以前,我可以用Postman测试我的RESTAPI。当我的访问令牌不正确或我没有特定资源的权限时,服务器响应如下: { "error": "access_denied", "error_description": "Access is denied" } 现在它一直将我重定向到/login页面。。。当我登录-它
spring boot starter父版从1.4.2
升级到1.5.2
变化完全把我弄糊涂了
以前,我可以用Postman测试我的RESTAPI。当我的访问令牌不正确或我没有特定资源的权限时,服务器响应如下:
{
"error": "access_denied",
"error_description": "Access is denied"
}
现在它一直将我重定向到/login
页面。。。当我登录-它显示我的资源没有任何OAuth2身份验证
我尝试禁用它,发现了以下神奇属性:
security.oauth2.resource.filter-order = 3
此行关闭了重定向到登录页面
不过,我的问题是:
- 就安全性而言,这两个版本之间发生了什么
- 这条“奇怪”的线是唯一有效的修复方法吗
- 这个登录页面的目的是什么,它使用的是什么身份验证(我在Google Chrome中检查了一个请求和响应,我看不到任何访问令牌和oauth2内容,所以它只使用用户存储库?)
我的代码中一些更重要的部分:
pom.xml
<!--- .... -->
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>1.5.2.RELEASE</version>
</parent>
<properties>
<!--- .... -->
<spring-security-oauth.version>2.1.0.RELEASE</spring-security-oauth.version>
<!--- .... -->
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- Monitor features -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-actuator</artifactId>
</dependency>
<!-- Security + OAuth2 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<version>${spring-security-oauth.version}</version>
</dependency>
<!--- .... -->
OAuth2.java
public class OAuth2 {
@EnableAuthorizationServer
@Configuration
@ComponentScan
public static class AuthorizationServer extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManagerBean;
@Autowired
private UserDetailsService userDetailsService;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("trusted_client")
.authorizedGrantTypes("password", "refresh_token")
.scopes("read", "write");
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(authenticationManagerBean).userDetailsService(userDetailsService);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
security.allowFormAuthenticationForClients();
}
}
@EnableResourceServer
@Configuration
@ComponentScan
public static class ResourceServer extends ResourceServerConfigurerAdapter {
@Autowired
private RoleHierarchy roleHierarchy;
private SecurityExpressionHandler<FilterInvocation> webExpressionHandler() {
DefaultWebSecurityExpressionHandler defaultWebSecurityExpressionHandler = new DefaultWebSecurityExpressionHandler();
defaultWebSecurityExpressionHandler.setRoleHierarchy(roleHierarchy);
return defaultWebSecurityExpressionHandler;
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests().expressionHandler(webExpressionHandler())
.antMatchers("/api/**").hasRole("DEVELOPER");
}
}
}
@EnableWebSecurity
@Configuration
@ComponentScan
public class Security extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Bean
public JpaAccountDetailsService userDetailsService(AccountsRepository accountsRepository) {
return new JpaAccountDetailsService(accountsRepository);
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
第一个和第二个问题的答案如下:
OAuth 2资源过滤器
OAuth2资源筛选器的默认顺序已从3更改为
SecurityProperties.ACCESS\u OVERRIDE\u ORDER-1。这将它放在
执行器端点,但在基本身份验证筛选器链之前。
可以通过设置恢复默认值
security.oauth2.resource.filter-order=3
/login页面只是spring重定向未授权用户的路径。由于您没有使用,并且Oauth2筛选器的位置错误,可能是使用了基本身份验证。好的,我现在知道了
@Cleto Gadelha向我指出了非常有用的信息
然而,我认为发布说明很不清楚或者遗漏了一些信息。除了OAuth2资源筛选器从3更改为SecurityProperties.ACCESS\u OVERRIDE\u ORDER-1之外,关键信息是默认的WebSecurityConfigureAdapter
顺序为100
因此,在1.5.x版之前,OAuth2资源服务器的顺序是3,其优先级高于WebSecurity配置适配器
在1.5.x版之后,OAuth2资源服务器顺序设置为SecurityProperties.ACCESS\u OVERRIDE\u order-1
(我认为是Integer.MAX_值-8
现在的优先级肯定比basicwebsecurityconfigureadapter
低
这就是为什么我从1.4.x迁移到1.5.x后会出现登录页面
因此,更优雅和类似java风格的解决方案是在WebSecurityConfigureAdapter
class上设置@Order(SecurityProperties.ACCESS\u OVERRIDE\u Order)
,这可能是由于未正确配置资源服务器造成的
@Override
public void configure(final HttpSecurity http) throws Exception {
// @formatter:off
http.csrf().disable().authorizeRequests()
// This is needed to enable swagger-ui interface.
.antMatchers("/swagger-ui.html","/swagger-resources/**","/webjars/**", "/v2/api-docs/**").permitAll()
.antMatchers("/api/v1/**").hasRole("TRUSTED_CLIENT")
.antMatchers("/api/v1/**").hasRole("USER")
.antMatchers("/api/v1/**").hasAuthority("ROLE_TRUSTED_CLIENT");
// @formatter:on
}
很好的调查。谢谢。无法将SecurityProperty解析为variable@ilovkatie我没有单独的Web安全配置适配器
。我也面临类似的问题,你能帮我吗。
@Override
public void configure(final HttpSecurity http) throws Exception {
// @formatter:off
http.csrf().disable().authorizeRequests()
// This is needed to enable swagger-ui interface.
.antMatchers("/swagger-ui.html","/swagger-resources/**","/webjars/**", "/v2/api-docs/**").permitAll()
.antMatchers("/api/v1/**").hasRole("TRUSTED_CLIENT")
.antMatchers("/api/v1/**").hasRole("USER")
.antMatchers("/api/v1/**").hasAuthority("ROLE_TRUSTED_CLIENT");
// @formatter:on
}