面对拒绝访问 (403) - spring security oauth2 中的禁止错误
Posted
技术标签:
【中文标题】面对拒绝访问 (403) - spring security oauth2 中的禁止错误【英文标题】:Facing Access Denied (403) - Forbidden error in spring security oauth2 【发布时间】:2017-12-20 21:45:24 【问题描述】:.antMatchers("/secure2/**").authenticated();
我已将我的一个 api 配置为受保护,当我尝试访问它时,它给了我访问被拒绝的错误消息,我不知道可能是什么原因。请注意,我正在传递有效的访问令牌。
我的场景: 基本上我已经在授权服务器中创建了注销休息 api,我希望这样,允许使用有效令牌的请求访问这个 api。
请求:
GET /auth/secure2 HTTP/1.1
Host: localhost:9191
Authorization: Bearer 33984141-1249-4465-a3aa-0b95a053fc63
Cache-Control: no-cache
Postman-Token: f4661790-a8e1-90ea-f6db-79cb37958cdf
回复:
"timestamp": 1500186837033,
"status": 403,
"error": "Forbidden",
"message": "Access Denied",
"path": "/auth/secure2"
我发现下面的方法返回 false 并因此引发访问被拒绝错误。
public final class ExpressionUtils
public static boolean evaluateAsBoolean(Expression expr, EvaluationContext ctx)
try
return ((Boolean) expr.getValue(ctx, Boolean.class)).booleanValue();
catch (EvaluationException e)
throw new IllegalArgumentException("Failed to evaluate expression '"
+ expr.getExpressionString() + "'", e);
以下是我在框架中调试时捕获的屏幕截图。还请检查评论中提到的图像。
代码:
SecurityConfiguration.java:
import org.springframework.beans.factory.annotation.Autowired;
@Configuration
@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter
@Autowired
private CustomUserDetailService userDetailsService;
@Bean
public PasswordEncoder passwordEncoder()
return new StandardPasswordEncoder();
@Override
protected void configure(AuthenticationManagerBuilder auth)
throws Exception
auth.authenticationProvider(authenticationProvider());
@Bean
public DaoAuthenticationProvider authenticationProvider()
DaoAuthenticationProvider authProvider
= new DaoAuthenticationProvider();
authProvider.setUserDetailsService(userDetailsService);
authProvider.setPasswordEncoder(encoder());
return authProvider;
@Bean
public ShaPasswordEncoder encoder()
return new ShaPasswordEncoder(256);
@Override
public void configure(WebSecurity web) throws Exception
@Override
protected void configure(HttpSecurity http) throws Exception
http
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler())
.and()
.csrf()
.requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize"))
.disable()
.headers()
.frameOptions().disable().disable()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.authorizeRequests()
.antMatchers("/hello/").permitAll()
.antMatchers("/secure3/").permitAll()
.antMatchers("/oauth/token/revoke/**").authenticated()
.antMatchers("/secure2/**").authenticated();
@Bean
public AccessDeniedHandler accessDeniedHandler()
return new CustomAccessDeniedHandler();
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
private static class GlobalSecurityConfiguration extends GlobalMethodSecurityConfiguration
public GlobalSecurityConfiguration()
@Override
protected MethodSecurityExpressionHandler createExpressionHandler()
return new OAuth2MethodSecurityExpressionHandler();
Oauth2Configuration.java
@Configuration
public class OAuth2Configuration
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter implements EnvironmentAware
private static final String ENV_OAUTH = "authentication.oauth.";
//private static final String PROP_CLIENTID = "clientid";
//private static final String PROP_SECRET = "secret";
private static final String PROP_ACCESS_TOKEN_VALIDITY_SECONDS = "accessTokenValidityInSeconds";
private static final String PROP_REFRESH_TOKEN_VALIDITY_SECONDS = "refreshTokenValidityInSeconds";
private RelaxedPropertyResolver propertyResolver;
@Autowired
private DataSource dataSource;
@Autowired
private CustomUserDetailService userDetailsService;
@Bean
public TokenStore tokenStore()
return new JdbcTokenStore(dataSource);
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints)
throws Exception
endpoints.tokenStore(tokenStore())
.userDetailsService(userDetailsService)
.tokenEnhancer(tokenEnhancer())
.accessTokenConverter(accessTokenConverter())
.authenticationManager(authenticationManager);
@Bean
public TokenEnhancer tokenEnhancer()
return new CustomTokenEnhancer();
@Bean
public DefaultAccessTokenConverter accessTokenConverter()
return new DefaultAccessTokenConverter();
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer)
throws Exception
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
clients
.inMemory()
.withClient("clientId")
.scopes("read", "write")
.authorities(Authorities.ROLE_ADMIN.name(), Authorities.ROLE_USER.name())
.authorizedGrantTypes("password", "refresh_token")
.accessTokenValiditySeconds(propertyResolver.getProperty(PROP_ACCESS_TOKEN_VALIDITY_SECONDS, Integer.class, 80))
.refreshTokenValiditySeconds(propertyResolver.getProperty(PROP_REFRESH_TOKEN_VALIDITY_SECONDS, Integer.class, 180))
.and().inMemory()
.withClient("clientid")
.scopes("read", "write")
.authorities(Authorities.ROLE_ADMIN.name(), Authorities.ROLE_USER.name())
.authorizedGrantTypes("client_credentials")
.secret("secret");
@Override
public void setEnvironment(Environment environment)
this.propertyResolver = new RelaxedPropertyResolver(environment, ENV_OAUTH);
控制器:
@Controller
@RequestMapping("/secure2")
public class SecureController1
@RequestMapping(method = RequestMethod.GET)
@ResponseBody
public String sayHello()
return "Secure Hello secure2!";
在哪些情况下会引发拒绝访问错误消息?如果需要任何其他信息,请告诉我。
【问题讨论】:
i.stack.imgur.com/vmOff.png i.stack.imgur.com/CwslH.png 这是授权服务器,我想保护授权服务器中的一些资源。例如,我有要保护的令牌撤销/注销休息 api。允许使用有效访问令牌的请求进行注销。 我在 SecurityConfiguration.configure(httpsecurity) 方法中有相关配置。 授权服务器中有哪些资源?应该只有授权和令牌端点。所有其他端点都是资源服务器的一部分。但是,如果您调用授权服务器,则不会应用 OAth2 令牌并且您是匿名的。只有资源服务器检查令牌。这就是你的 403 的原因。 【参考方案1】:我使用了这些代码,它们运行良好。
OAuth2AuthorizationServerConfig.java:
@Configuration
@EnableAuthorizationServer
public class OAuth2AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
// Configure the token store and authentication manager
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception
//@formatter:off
endpoints
.tokenStore(tokenStore())
.accessTokenConverter(accessTokenConverter()) // added for JWT
.authenticationManager(authenticationManager);
//@formatter:on
// Configure a client store. In-memory for simplicity, but consider other
// options for real apps.
//It is not necessary.works even without this func:)
// @Override
// public void configure(AuthorizationServerSecurityConfigurer oauthServer)
// throws Exception
// oauthServer
// .tokenKeyAccess("permitAll()")
// .checkTokenAccess("isAuthenticated()");
//
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception
//@formatter:off
clients
.inMemory()
.withClient("myclient")//username in basic auth header
.secret ("noop123")//password in basic auth header;
.authorizedGrantTypes("authorization_code", "implicit", "password", "client_credentials", "refresh_token")
.scopes("read")
//.redirectUris("http://localhost:9191/x")
.accessTokenValiditySeconds(86400); // 24 hours
//@formatter:on
// A token store bean. JWT token store
@Bean
public TokenStore tokenStore()
return new JwtTokenStore(accessTokenConverter()); // For JWT. Use in-memory, jdbc, or other if not JWT
// Token converter. Needed for JWT
@Bean
public JwtAccessTokenConverter accessTokenConverter()
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey("123"); // symmetric key
return converter;
// Token services. Needed for JWT
@Bean
@Primary
public DefaultTokenServices tokenServices()
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
return defaultTokenServices;
// @Bean
//
// public PasswordEncoder passwordEncoder ()
//
// return new BCryptPasswordEncoder();
//
//
WebSecurityConfig:
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter
@Autowired
private UserDetailsService userDetailsService;
//It is not important to use this func. /oauth/token is the default path of spring security to use oauth2. she is so clever!! :)
// @Override
// protected void configure(HttpSecurity http) throws Exception
//
//
// http.authorizeRequests()
// .antMatchers(HttpMethod.POST, "/oauth/token").permitAll()
// .anyRequest().authenticated();
//
@Autowired
public void configureGlobal(final AuthenticationManagerBuilder auth) throws Exception
auth.inMemoryAuthentication()
.withUser("user").password("noopuser").roles("ROLE");
//
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception
// auth.userDetailsService(userDetailsService)
// .passwordEncoder(passwordEncoder());
//
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception
return super.authenticationManagerBean();
//
// @Bean
// public PasswordEncoder passwordEncoder()
// return new BCryptPasswordEncoder();
//
输出: 请注意,code 和 postman 中使用的用户名和密码的值必须相同。
enter image description here enter image description here
希望对你有所帮助:)
【讨论】:
以上是关于面对拒绝访问 (403) - spring security oauth2 中的禁止错误的主要内容,如果未能解决你的问题,请参考以下文章
在 Spring Security 中启用 CSRF 时,访问被拒绝 403
Spring Security 4.1 升级 - 错误 403 访问被拒绝
Spring Security 总是返回 403 被禁止,访问被拒绝
Spring security hasRole() 给出错误 403 - 访问被拒绝