【发布时间】: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!";
}
}
在哪些情况下会引发拒绝访问错误消息?如果需要任何其他信息,请告诉我。
【问题讨论】:
-
这是授权服务器,我想保护授权服务器中的一些资源。例如,我有要保护的令牌撤销/注销休息 api。允许使用有效访问令牌的请求进行注销。
-
我在 SecurityConfiguration.configure(httpsecurity) 方法中有相关配置。
-
授权服务器中有哪些资源?应该只有授权和令牌端点。所有其他端点都是资源服务器的一部分。但是,如果您调用授权服务器,则不会应用 OAth2 令牌并且您是匿名的。只有资源服务器检查令牌。这就是你的 403 的原因。
标签: spring-boot spring-security spring-security-oauth2