.antMatchers("/secure2/**").authenticated();
我已将其中一个api配置为受保护,当我尝试访问它时,它给出了Access Denied错误消息,我不知道可能是什么原因。请注意,我正在传递有效的访问令牌。
我的方案: 基本上我已经在授权服务器中创建了logout rest 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!";
}
}
它引发访问被拒绝错误消息的场景是什么?如果需要任何其他信息,请告诉我。
答案 0 :(得分: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 ("{noop}123")//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("{noop}user").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();
// }
}
输出: 请注意,代码和邮递员中使用的用户名和密码的值必须相同。
enter image description here enter image description here
希望对您有所帮助:)