bar*_*lik 7 java spring oauth spring-security spring-security-oauth2
As I see Spring Security OAuth2.x project was moved to Spring Security 5.2.x. I try to implement authorization and resource server in new way. Everythin is working correctly except one thing - @PreAuthorize annotation. When I try to use this with standard @PreAuthorize("hasRole('ROLE_USER')") I always get forbidden. What I see is that the Principal object which is type of org.springframework.security.oauth2.jwt.Jwt is not able to resolve authorities and I have no idea why.
org.springframework.security.oauth2.server.resource.authentication.JwtAuthenticationToken@44915f5f: Principal: org.springframework.security.oauth2.jwt.Jwt@2cfdbd3; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@ffffa64e: RemoteIpAddress: 172.19.0.1; SessionId: null; Granted Authorities: SCOPE_read, SCOPE_write
Run Code Online (Sandbox Code Playgroud)
And claims after casting it to Jwt
{user_name=user, scope=["read","write"], exp=2019-12-18T13:19:29Z, iat=2019-12-18T13:19:28Z, authorities=["ROLE_USER","READ_ONLY"], client_id=sampleClientId}
Run Code Online (Sandbox Code Playgroud)
Security Server Configuration
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
private DataSource dataSource;
@Autowired
private AuthenticationManager authenticationManager;
@Bean
public KeyPair keyPair() {
ClassPathResource ksFile = new ClassPathResource("mytest.jks");
KeyStoreKeyFactory keyStoreKeyFactory = new KeyStoreKeyFactory(ksFile, "mypass".toCharArray());
return keyStoreKeyFactory.getKeyPair("mytest");
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setKeyPair(keyPair());
return converter;
}
@Bean
public JWKSet jwkSet() {
RSAKey key = new Builder((RSAPublicKey) keyPair().getPublic()).build();
return new JWKSet(key);
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.jdbc(dataSource);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
endpoints.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter())
.authenticationManager(authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
}
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
private UserDetailsService userDetailsService;
public SecurityConfiguration(UserDetailsService userDetailsService) {
this.userDetailsService = userDetailsService;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.mvcMatchers("/.well-known/jwks.json")
.permitAll()
.anyRequest()
.authenticated();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
}
}
Run Code Online (Sandbox Code Playgroud)
Resource server configuration
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResuorceServerConfiguration extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest()
.authenticated()
.and()
.oauth2ResourceServer()
.jwt();
}
}
Run Code Online (Sandbox Code Playgroud)
Maybe someone had similar issue?
Ele*_*ana 21
默认情况下,资源服务器根据"scope"声明填充权限。
如果Jwt包含名称为"scope"or 的声明"scp",则 Spring Security 将使用该声明中的值通过为每个值添加前缀来构造权限"SCOPE_"。
在您的示例中,其中一项声明是scope=["read","write"].
这意味着权限列表将包括"SCOPE_read"和"SCOPE_write"。
您可以通过在安全配置中提供自定义身份验证转换器来修改默认权限映射行为。
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(getJwtAuthenticationConverter());
Run Code Online (Sandbox Code Playgroud)
然后在您的 实现中getJwtAuthenticationConverter,您可以配置Jwt映射到权限列表的方式。
http
.authorizeRequests()
.anyRequest().authenticated()
.and()
.oauth2ResourceServer()
.jwt()
.jwtAuthenticationConverter(getJwtAuthenticationConverter());
Run Code Online (Sandbox Code Playgroud)
将其添加到您的 SecurityConfig
.jwt()
.jwtAuthenticationConverter(jwtAuthenticationConverter());
Run Code Online (Sandbox Code Playgroud)
还有转换器
private JwtAuthenticationConverter jwtAuthenticationConverter() {
// create a custom JWT converter to map the "roles" from the token as granted authorities
JwtGrantedAuthoritiesConverter jwtGrantedAuthoritiesConverter = new JwtGrantedAuthoritiesConverter();
jwtGrantedAuthoritiesConverter.setAuthoritiesClaimName("roles");
jwtGrantedAuthoritiesConverter.setAuthorityPrefix("ROLE_");
JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(jwtGrantedAuthoritiesConverter);
return jwtAuthenticationConverter;
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
6204 次 |
| 最近记录: |