转到Spring Boot 1.5.1和OAuth2 + JWT令牌 - 错误401未经授权
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了转到Spring Boot 1.5.1和OAuth2 + JWT令牌 - 错误401未经授权相关的知识,希望对你有一定的参考价值。
我正在尝试将我的项目移动到Spring Boot 1.5.1,现在我的Outh2 + JWT令牌配置停止工作。
现在我在执行以下测试时收到401错误:
RestTemplate restTemplate = new RestTemplate();
CreateDecisionRequest decisionRequest = new CreateDecisionRequest(name, description, url, imageUrl, parentDecisionId, tenantId);
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
headers.add(SecurityTestUtils.AUTH_HEADER_NAME, "Bearer " + accessToken);
HttpEntity<CreateDecisionRequest> requestEntity = new HttpEntity<CreateDecisionRequest>(decisionRequest, headers);
ResponseEntity<DecisionResponse> responseEntity = restTemplate.exchange(String.format("http://localhost:%d/api/v1.0/decisions", port), HttpMethod.POST, requestEntity, DecisionResponse.class);
这是我的RestController:
@RestController
@RequestMapping("/v1.0/decisions")
public class DecisionsController {
@Autowired
private DecisionService decisionService;
@PreAuthorize("hasAuthority(T(Permission).CREATE_DECISION)")
@RequestMapping(method = RequestMethod.POST)
public DecisionResponse createDecision(@Valid @RequestBody CreateDecisionRequest request, Authentication authentication) {
User user = SecurityUtils.getAuthenticatedUser(authentication);
Decision decision = decisionService.createDecision(request.getName(), request.getDescription(), request.getUrl(), request.getImageUrl(), request.getParentDecisionId(), request.getTenantId(), user.getId());
return new DecisionResponse(decision);
}
}
这是OAuth2ServerConfig:
@Configuration
public class OAuth2ServerConfig {
public static final String RESOURCE_ID = "restservice";
public static final String example_CLIENT_ID = "example_client_id";
@Value("${jwt.access.token.converter.signing.key}")
private String jwtAccessTokenConverterSigningKey;
@Value("${jwt.access.token.validity.seconds}")
private int accessTokenValiditySeconds;
@Autowired
private UserDetailsService userDetailsService;
@Bean
@Primary
public DefaultTokenServices tokenServices() {
DefaultTokenServices tokenServices = new DefaultTokenServices();
tokenServices.setTokenStore(tokenStore());
tokenServices.setSupportRefreshToken(true);
tokenServices.setAccessTokenValiditySeconds(accessTokenValiditySeconds);
return tokenServices;
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new TenantAwareAccessTokenConverter();
converter.setSigningKey(jwtAccessTokenConverterSigningKey);
DefaultAccessTokenConverter accessTokenConverter = new DefaultAccessTokenConverter();
DefaultUserAuthenticationConverter userTokenConverter = new DefaultUserAuthenticationConverter();
userTokenConverter.setUserDetailsService(userDetailsService);
accessTokenConverter.setUserTokenConverter(userTokenConverter);
converter.setAccessTokenConverter(accessTokenConverter);
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Configuration
@EnableAuthorizationServer
protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Value("${jwt.access.token.validity.seconds}")
private int accessTokenValiditySeconds;
@Autowired
private TokenStore tokenStore;
@Autowired
private TokenEnhancer tokenEnhancer;
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
// @formatter:off
endpoints
.tokenStore(tokenStore)
.tokenEnhancer(tokenEnhancer)
.authenticationManager(this.authenticationManager);
// @formatter:on
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
// @formatter:off
clients
.inMemory()
.withClient("clientapp")
.authorizedGrantTypes("password","refresh_token")
.authorities("ROLE_CLIENT")
.scopes("read", "write")
.resourceIds(RESOURCE_ID)
.secret("123456")
.and()
.withClient(example_CLIENT_ID)
.authorizedGrantTypes("implicit")
.scopes("read", "write")
.autoApprove(true)
.and()
.withClient("my-trusted-client")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.scopes("read", "write", "trust")
.accessTokenValiditySeconds(accessTokenValiditySeconds);
// @formatter:on
}
}
@Configuration
@EnableResourceServer
protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
@Autowired
private ResourceServerTokenServices tokenService;
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
// @formatter:off
resources
.resourceId(RESOURCE_ID)
.tokenServices(tokenService);
// @formatter:on
}
@Override
public void configure(HttpSecurity http) throws Exception {
// @formatter:off
http
.antMatcher("/v1.0/**").authorizeRequests()
.antMatchers("/v1.0/users/**").permitAll()
.antMatchers("/v1.0/tenants/**").permitAll()
.antMatchers("/v1.0/decisions/**").permitAll()
.antMatchers("/v1.0/comments/**").permitAll()
.antMatchers("/v1.0/commentable/**").permitAll()
.antMatchers("/v1.0/import/**").permitAll()
.antMatchers("/swagger**").permitAll()
.anyRequest().authenticated()
.and()
.csrf().disable()
.sessionManagement().sessionCreationPolicy(STATELESS);
// @formatter:on
}
}
}
WebSecurityConfig:
@Configuration
@EnableWebSecurity(debug = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailsService userDetailsService;
@Value("${logout.success.url}")
private String logoutSuccessUrl;
@Override
protected void configure(HttpSecurity http) throws Exception {
// @formatter:off
http.addFilterBefore(new CorsFilter(), ChannelProcessingFilter.class);
http
.csrf().ignoringAntMatchers("/v1.0/**", "/logout")
.and()
.authorizeRequests()
.antMatchers("/oauth/authorize").authenticated()
//Anyone can access the urls
.antMatchers("/signin/**").permitAll()
.antMatchers("/v1.0/**").permitAll()
.antMatchers("/auth/**").permitAll()
.antMatchers("/actuator/health").permitAll()
.antMatchers("/actuator/**").hasAuthority(Permission.READ_ACTUATOR_DATA)
.antMatchers("/login").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/login")
.failureUrl("/login?error=true")
.usernameParameter("username")
.passwordParameter("password")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessUrl(logoutSuccessUrl)
.permitAll();
// @formatter:on
}
/**
* Configures the authentication manager bean which processes authentication requests.
*/
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(new BCryptPasswordEncoder());
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
}
MethodSecurityConfig:
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true)
public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration {
private DefaultMethodSecurityExpressionHandler defaultMethodExpressionHandler = new DefaultMethodSecurityExpressionHandler();
@Override
protected MethodSecurityExpressionHandler createExpressionHandler() {
return defaultMethodExpressionHandler;
}
public class DefaultMethodSecurityExpressionHandler extends org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler {
@Override
public StandardEvaluationContext createEvaluationContextInternal(final Authentication auth, final MethodInvocation mi) {
StandardEvaluationContext standardEvaluationContext = super.createEvaluationContextInternal(auth, mi);
((StandardTypeLocator) standardEvaluationContext.getTypeLocator()).registerImport(Permission.class.getPackage().getName());
return standardEvaluationContext;
}
}
}
由于某种原因OAuth2AuthenticationProcessingFilter
没有调用。
在调试中,我可以看到以下过滤器链:
2017-02-02 21:49:06 [main] INFO o.s.s.web.DefaultSecurityFilterChain -
Creating filter chain: OrRequestMatcher [requestMatchers=[Ant [pattern='/oauth/token'], Ant [pattern='/oauth/token_key'], Ant [pattern='/oauth/check_token']]], [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@7ecb7520, org.springframework.security.web.context.SecurityContextPersistenceFilter@139dd09d, org.springframework.security.web.header.HeaderWriterFilter@4920b753, org.springframework.security.web.authentication.logout.LogoutFilter@4a3de11b, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@7be4e93a, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@4ebbfb1b, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@3b59e044, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@3c92ea51, org.springframework.security.web.session.SessionManagementFilter@46753361, org.springframework.security.web.access.ExceptionTranslationFilter@27542320, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@64b1a881]
2017-02-02 21:49:06 [main] INFO o.s.s.web.DefaultSecurityFilterChain -
Creating filter chain: org.springframework.security.web.util.matcher.AnyRequestMatcher@1, [com.decisionwanted.domain.api.filter.CorsFilter@4e672059, org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@60076ce9, org.springframework.security.web.context.SecurityContextPersistenceFilter@755a147b, org.springframework.security.web.header.HeaderWriterFilter@2a86df56, org.springframework.security.web.csrf.CsrfFilter@6de4a2cd, org.springframework.security.web.authentication.logout.LogoutFilter@3e8b6e6c, org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter@6a85fc62, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@1ee9fb22, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@209ebc6, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@424d518d, org.springframework.security.web.session.SessionManagementFilter@3de02bc0, org.springframework.security.web.access.ExceptionTranslationFilter@58d661cb, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@fe5a1ad]
2017-02-02 21:49:06 [main] INFO o.s.s.web.DefaultSecurityFilterChain -
Creating filter chain: Ant [pattern='/actuator/**'], [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@75a8ec32, org.springframework.security.web.context.SecurityContextPersistenceFilter@25e34521, org.springframework.security.web.header.HeaderWriterFilter@2899d7a4, org.springframework.security.web.authentication.logout.LogoutFilter@5129c8c0, org.springframework.security.web.authentication.www.BasicAuthenticationFilter@61f81842, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@1bb0a050, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@7df26075, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@2cb0d5c6, org.springframework.security.web.session.SessionManagementFilter@435184b, org.springframework.security.web.access.ExceptionTranslationFilter@66cb04c1, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@1a563725]
2017-02-02 21:49:06 [main] INFO o.s.s.web.DefaultSecurityFilterChain -
Creating filter chain: Ant [pattern='/v1.0/**'], [org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter@378f95bc, org.springframework.security.web.context.SecurityContextPersistenceFilter@5d942ffb, org.springframework.security.web.header.HeaderWriterFilter@77699f4c, org.springframework.security.web.authentication.logout.LogoutFilter@4b16fede, org.springframework.security.oauth2.provider.authentication.OAuth2AuthenticationProcessingFilter@2a135489, org.springframework.security.web.savedrequest.RequestCacheAwareFilter@2d26b41b, org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter@160ecd0c, org.springframework.security.web.authentication.AnonymousAuthenticationFilter@55478708, org.springframework.security.web.session.SessionManagementFilter@4ba2cce7, org.springframework.security.web.access.ExceptionTranslationFilter@46d6d280, org.springframework.security.web.access.intercept.FilterSecurityInterceptor@16807d05]
看起来有一些原因pattern='/v1.0/**
(OAuth2AuthenticationProcessingFilter
存在的地方)的过滤器链在我试图访问我的测试中的以下url时没有调用:http://localhost:%d/api/v1.0/decisions
这是一个安全调试输出:
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher -
Trying to match using Ant [pattern='/oauth/token']
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/v1.0/decisions'; against '/oauth/token'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher -
Trying to match using Ant [pattern='/oauth/token_key']
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/v1.0/decisions'; against '/oauth/token_key'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher -
Trying to match using Ant [pattern='/oauth/check_token']
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/v1.0/decisions'; against '/oauth/check_token'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher -
No matches found
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher -
Trying to match using Ant [pattern='/oauth/token']
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/v1.0/decisions'; against '/oauth/token'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher -
Trying to match using Ant [pattern='/oauth/token_key']
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/v1.0/decisions'; against '/oauth/token_key'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher -
Trying to match using Ant [pattern='/oauth/check_token']
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/v1.0/decisions'; against '/oauth/check_token'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher -
No matches found
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions at position 1 of 13 in additional filter chain; firing Filter: 'CorsFilter'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions at position 2 of 13 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions at position 3 of 13 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository -
No HttpSession currently exists
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository -
No SecurityContext was available from the HttpSession: null. A new one will be created.
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions at position 4 of 13 in additional filter chain; firing Filter: 'HeaderWriterFilter'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.h.writers.HstsHeaderWriter -
Not injecting HSTS header since it did not match the requestMatcher org.springframework.security.web.header.writers.HstsHeaderWriter$SecureRequestMatcher@21d3e567
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions at position 5 of 13 in additional filter chain; firing Filter: 'CsrfFilter'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.matcher.AndRequestMatcher -
Trying to match using org.springframework.security.web.csrf.CsrfFilter$DefaultRequiresCsrfMatcher@74b80eab
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.matcher.AndRequestMatcher -
Trying to match using NegatedRequestMatcher [requestMatcher=OrRequestMatcher [requestMatchers=[Ant [pattern='/v1.0/**'], Ant [pattern='/logout']]]]
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher -
Trying to match using Ant [pattern='/v1.0/**']
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/v1.0/decisions'; against '/v1.0/**'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.matcher.OrRequestMatcher -
matched
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.NegatedRequestMatcher -
matches = false
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.matcher.AndRequestMatcher -
Did not match
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions at position 6 of 13 in additional filter chain; firing Filter: 'LogoutFilter'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/v1.0/decisions'; against '/logout'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions at position 7 of 13 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/v1.0/decisions'; against '/login'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions at position 8 of 13 in additional filter chain; firing Filter: 'RequestCacheAwareFilter'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions at position 9 of 13 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions at position 10 of 13 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.a.AnonymousAuthenticationFilter -
Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions at position 11 of 13 in additional filter chain; firing Filter: 'SessionManagementFilter'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions at position 12 of 13 in additional filter chain; firing Filter: 'ExceptionTranslationFilter'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions at position 13 of 13 in additional filter chain; firing Filter: 'FilterSecurityInterceptor'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/v1.0/decisions'; against '/logout'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/v1.0/decisions'; against '/oauth/authorize'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/v1.0/decisions'; against '/signin/**'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.u.m.AntPathRequestMatcher -
Checking match of request : '/v1.0/decisions'; against '/v1.0/**'
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor -
Secure object: FilterInvocation: URL: /v1.0/decisions; Attributes: [permitAll]
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor -
Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.access.vote.AffirmativeBased -
Voter: org.springframework.security.web.access.expression.WebExpressionVoter@3d885e49, returned: 1
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor -
Authorization successful
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.a.i.FilterSecurityInterceptor -
RunAsManager did not change Authentication object
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.security.web.FilterChainProxy -
/v1.0/decisions reached end of additional filter chain; proceeding with original chain
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.a.i.a.MethodSecurityInterceptor -
Secure object: ReflectiveMethodInvocation: public com.decisionwanted.domain.api.dto.decision.DecisionResponse com.decisionwanted.domain.api.controller.decisions.DecisionsController.createDecision(com.decisionwanted.domain.api.dto.decision.CreateDecisionRequest,org.springframework.security.core.Authentication); target is of class [com.decisionwanted.domain.api.controller.decisions.DecisionsController]; Attributes: [[authorize: 'hasAuthority(T(Permission).CREATE_DECISION)', filter: 'null', filterTarget: 'null']]
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.a.i.a.MethodSecurityInterceptor -
Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055e4a6: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@957e: RemoteIpAddress: 127.0.0.1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.access.vote.AffirmativeBased -
Voter: org.springframework.security.access.prepost.PreInvocationAuthorizationAdviceVoter@6679d66a, returned: -1
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.access.vote.AffirmativeBased -
Voter: org.springframework.security.access.annotation.Jsr250Voter@2ffd169b, returned: 0
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.access.vote.AffirmativeBased -
Voter: org.springframework.security.access.vote.RoleVoter@8384b20, returned: 0
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.access.vote.AffirmativeBased -
Voter: org.springframework.security.access.vote.AuthenticatedVoter@7a1c554f, returned: 0
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository -
SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession.
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.a.ExceptionTranslationFilter -
Chain processed normally
2017-02-02 22:10:59 [http-nio-auto-1-exec-2] DEBUG o.s.s.w.c.SecurityContextPersistenceFilter -
SecurityContextHolder now cleared, as request processing completed
2017-02-02 22:10:59 [Thread-5] INFO o.s.b.c.e.AnnotationConfigEmbeddedWebApplicationContext -
Closing org.springframework.boot.context.embedded.AnnotationConfigEmbeddedWebApplicationContext@41d426b5: startup date [Thu Feb 02 22:10:19 EET 2017]; root of context hierarchy
2017-02-02 22:10:59 [Thread-5] INFO o.s.c.s.DefaultLifecycleProcessor -
Stopping beans in phase 2147483647
如何解决这个问题?
我找到了这个问题的原因:
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-1.5-Release-Notes
OAuth 2 Resource Filter
The default order of the OAuth2 resource filter has changed from 3 to SecurityProperties.ACCESS_OVERRIDE_ORDER - 1. This places it after the actuator endpoints but before the basic authentication filter chain. The default can be restored by setting security.oauth2.resource.filter-order = 3
因此,将security.oauth2.resource.filter-order = 3
添加到application.properties
就可以了!现在一切都按预期工作。
以上是关于转到Spring Boot 1.5.1和OAuth2 + JWT令牌 - 错误401未经授权的主要内容,如果未能解决你的问题,请参考以下文章
让 oauth2 与 spring-boot 和 rest 一起工作
使用Spring boot的OAuth2认证服务器和资源服务器
带有 Jersey 和 Spring Security OAuth2 的 Spring Boot