我在 springboot 1.5.6.RELEASE中 使用了oauth2,并且在oauth2中使用了jdbc身份验证。
我添加了该属性: security.oauth2.resource.filter-order = 3
security.oauth2.resource.filter-order = 3
1- AuthorizationServerConfigurerAdapter:
@Configuration @EnableAuthorizationServer public class OAuth2Config extends AuthorizationServerConfigurerAdapter { @Autowired @Qualifier("authenticationManagerBean") @Lazy private AuthenticationManager authenticationManager; @Autowired private Environment env; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { // endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager); endpoints.authenticationManager(authenticationManager); } @Bean public TokenStore tokenStore() { return new JdbcTokenStore(dataSource()); } @Override public void configure(AuthorizationServerSecurityConfigurer security) throws Exception { security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()"); } @Override public void configure(ClientDetailsServiceConfigurer clients) throws Exception { clients.jdbc(dataSource()); } @Bean public DataSource dataSource() { DriverManagerDataSource dataSource = new DriverManagerDataSource(); dataSource.setDriverClassName(env.getProperty("spring.datasource.driver-class-name")); dataSource.setUrl(env.getProperty("spring.datasource.url")); dataSource.setUsername(env.getProperty("spring.datasource.username")); dataSource.setPassword(env.getProperty("spring.datasource.password")); return dataSource; } }
2- ResourceServerConfigurerAdapter
@EnableResourceServer public class OAuth2ResourceServer extends ResourceServerConfigurerAdapter { @Override public void configure(HttpSecurity http) throws Exception { http.antMatcher("/ws/**").authorizeRequests().anyRequest().authenticated(); } }
3- SecurityConfig
@Configuration @EnableWebSecurity class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired private UserDetailsService userDetailsService; @Autowired private CustomAuthenticationSuccessHandler successHandler; @Override protected void configure(HttpSecurity http) throws Exception { http.csrf().disable(); http.authorizeRequests() .antMatchers("/", "/registerCompany", "/registerEmployee", "/jobs", "/returnPassword", "/resetPassword", "/faces/public/**", "/resources/**", "/template/**", "/faces/fonts/*", "/faces/javax.faces.resource/**", "/ws/**", "/login", "/oauth/**", "/error") .permitAll().antMatchers("/admin/**", "/faces/admin/**").hasAuthority("ROLE_ADMIN") .antMatchers("/employeeProfile", "/employeeMainPage", "/employeeAskJob").hasAuthority("ROLE_EMPLOYEE") .antMatchers("/companyProfile", "/companyMainPage", "/companyPostJob", "/companySearch", "/branchProfile") .hasAnyAuthority("ROLE_COMPANY,ROLE_BRANCH,ROLE_ADMIN").anyRequest().fullyAuthenticated().and() .formLogin().loginPage("/login").permitAll().successHandler(successHandler).failureUrl("/login?error") .usernameParameter("username").passwordParameter("password").and().logout().deleteCookies("JSESSIONID") .logoutUrl("/logout").deleteCookies("remember-me").logoutSuccessUrl("/").permitAll().and().rememberMe(); // http.sessionManagement().invalidSessionUrl("/login?invalidSession"); // cache resources http.headers().addHeaderWriter(new DelegatingRequestMatcherHeaderWriter( new AntPathRequestMatcher("/javax.faces.resource/**"), new HeaderWriter() { @Override public void writeHeaders(HttpServletRequest request, HttpServletResponse response) { response.addHeader("Cache-Control", "private, max-age=86400"); } })).defaultsDisabled(); } @Override @Bean public AuthenticationManager authenticationManagerBean() throws Exception { return super.authenticationManagerBean(); } @Override public void configure(AuthenticationManagerBuilder auth) throws Exception { auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder()); } @Bean public PasswordEncoder passwordEncoder() { return new BCryptPasswordEncoder(11); } }
我试图使用邮递员生成带有URL的邮寄请求的令牌,http://localhost:8082/dawam2/oauth/token?grant_type=password 并且我使用 基本身份验证 并设置 username = myclient_id 和 password = myclient_secret 。因此,生成了 标头(授权:Basic Basic Basic bXljbGllbnRfaWQ6bXljbGllbnRfc2VjcmV0) ,并设置了标头 Content-Type:application / x-www-form-urlencoded; charset = utf-8。
http://localhost:8082/dawam2/oauth/token?grant_type=password
我得到的响应而不是生成的令牌:
!doctype html><html lang="en"><head><title>HTTP Status 404 – Not Found</title><style type="text/css">h1 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:22px;} h2 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:16px;} h3 {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;font-size:14px;} body {font-family:Tahoma,Arial,sans-serif;color:black;background-color:white;} b {font-family:Tahoma,Arial,sans-serif;color:white;background-color:#525D76;} p {font-family:Tahoma,Arial,sans-serif;background:white;color:black;font-size:12px;} a {color:black;} a.name {color:black;} .line {height:1px;background-color:#525D76;border:none;}</style></head><body><h1>HTTP Status 404 – Not Found</h1><hr class="line" /><p><b>Type</b> Status Report</p><p><b>Message</b> Not Found</p><p><b>Description</b> The origin server did not find a current representation for the target resource or is not willing to disclose that one exists.</p><hr class="line" /><h3>Apache Tomcat/9.0.0.M18</h3></body></html>
以下是调试信息:
2017-09-26 15:32:16,833 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/oauth/token'] 2017-09-26 15:32:16,833 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/token' 2017-09-26 15:32:16,833 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - matched 2017-09-26 15:32:16,833 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 1 of 11 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' 2017-09-26 15:32:16,833 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 2 of 11 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 2017-09-26 15:32:16,833 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 3 of 11 in additional filter chain; firing Filter: 'HeaderWriterFilter' 2017-09-26 15:32:16,833 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@1d47c7a 2017-09-26 15:32:16,833 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 4 of 11 in additional filter chain; firing Filter: 'LogoutFilter' 2017-09-26 15:32:16,833 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', GET] 2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/logout' 2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', POST] 2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /oauth/token' doesn't match 'POST /logout 2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', PUT] 2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /oauth/token' doesn't match 'PUT /logout 2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', DELETE] 2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /oauth/token' doesn't match 'DELETE /logout 2017-09-26 15:32:16,834 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - No matches found 2017-09-26 15:32:16,834 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 5 of 11 in additional filter chain; firing Filter: 'BasicAuthenticationFilter' 2017-09-26 15:32:16,834 DEBUG o.s.s.w.a.w.BasicAuthenticationFilter - Basic Authentication Authorization header found for user 'myclient_id' 2017-09-26 15:32:16,834 DEBUG o.s.s.a.ProviderManager - Authentication attempt using org.springframework.security.authentication.dao.DaoAuthenticationProvider 2017-09-26 15:32:16,849 DEBUG o.s.s.w.a.w.BasicAuthenticationFilter - Authentication success: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d9cf8114: Principal: org.springframework.security.core.userdetails.User@6a9879e3: Username: myclient_id; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_EMPLOYEE; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_EMPLOYEE 2017-09-26 15:32:16,850 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 6 of 11 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' 2017-09-26 15:32:16,850 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 7 of 11 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' 2017-09-26 15:32:16,850 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 8 of 11 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' 2017-09-26 15:32:16,850 DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - SecurityContextHolder not populated with anonymous token, as it already contained: 'org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d9cf8114: Principal: org.springframework.security.core.userdetails.User@6a9879e3: Username: myclient_id; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_EMPLOYEE; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_EMPLOYEE' 2017-09-26 15:32:16,850 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 9 of 11 in additional filter chain; firing Filter: 'SessionManagementFilter' 2017-09-26 15:32:16,850 DEBUG o.s.s.w.a.s.CompositeSessionAuthenticationStrategy - Delegating to org.springframework.security.web.authentication.session.ChangeSessionIdAuthenticationStrategy@15d6aaa 2017-09-26 15:32:16,850 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 10 of 11 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' 2017-09-26 15:32:16,850 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password at position 11 of 11 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' 2017-09-26 15:32:16,850 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/oauth/token'; against '/oauth/token' 2017-09-26 15:32:16,850 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Secure object: FilterInvocation: URL: /oauth/token?grant_type=password; Attributes: [fullyAuthenticated] 2017-09-26 15:32:16,850 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Previously Authenticated: org.springframework.security.authentication.UsernamePasswordAuthenticationToken@d9cf8114: Principal: org.springframework.security.core.userdetails.User@6a9879e3: Username: myclient_id; Password: [PROTECTED]; Enabled: true; AccountNonExpired: true; credentialsNonExpired: true; AccountNonLocked: true; Granted Authorities: ROLE_EMPLOYEE; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_EMPLOYEE 2017-09-26 15:32:16,851 DEBUG o.s.s.access.vote.AffirmativeBased - Voter: org.springframework.security.web.access.expression.WebExpressionVoter@14cb584, returned: 1 2017-09-26 15:32:16,851 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - Authorization successful 2017-09-26 15:32:16,851 DEBUG o.s.s.w.a.i.FilterSecurityInterceptor - RunAsManager did not change Authentication object 2017-09-26 15:32:16,851 DEBUG o.s.security.web.FilterChainProxy - /oauth/token?grant_type=password reached end of additional filter chain; proceeding with original chain 2017-09-26 15:32:16,853 DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally 2017-09-26 15:32:16,853 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed 2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/oauth/token'] 2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/error'; against '/oauth/token' 2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/oauth/token_key'] 2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/error'; against '/oauth/token_key' 2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/oauth/check_token'] 2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/error'; against '/oauth/check_token' 2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - No matches found 2017-09-26 15:32:16,854 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 1 of 12 in additional filter chain; firing Filter: 'WebAsyncManagerIntegrationFilter' 2017-09-26 15:32:16,854 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 2 of 12 in additional filter chain; firing Filter: 'SecurityContextPersistenceFilter' 2017-09-26 15:32:16,854 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No HttpSession currently exists 2017-09-26 15:32:16,854 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - No SecurityContext was available from the HttpSession: null. A new one will be created. 2017-09-26 15:32:16,854 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 3 of 12 in additional filter chain; firing Filter: 'HeaderWriterFilter' 2017-09-26 15:32:16,854 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 4 of 12 in additional filter chain; firing Filter: 'LogoutFilter' 2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', GET] 2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Checking match of request : '/error'; against '/logout' 2017-09-26 15:32:16,854 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', POST] 2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /error' doesn't match 'POST /logout 2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', PUT] 2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /error' doesn't match 'PUT /logout 2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - Trying to match using Ant [pattern='/logout', DELETE] 2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /error' doesn't match 'DELETE /logout 2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.matcher.OrRequestMatcher - No matches found 2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 5 of 12 in additional filter chain; firing Filter: 'UsernamePasswordAuthenticationFilter' 2017-09-26 15:32:16,855 DEBUG o.s.s.w.u.m.AntPathRequestMatcher - Request 'GET /error' doesn't match 'POST /login 2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 6 of 12 in additional filter chain; firing Filter: 'RequestCacheAwareFilter' 2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 7 of 12 in additional filter chain; firing Filter: 'SecurityContextHolderAwareRequestFilter' 2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 8 of 12 in additional filter chain; firing Filter: 'RememberMeAuthenticationFilter' 2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 9 of 12 in additional filter chain; firing Filter: 'AnonymousAuthenticationFilter' 2017-09-26 15:32:16,855 DEBUG o.s.s.w.a.AnonymousAuthenticationFilter - Populated SecurityContextHolder with anonymous token: 'org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS' 2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 10 of 12 in additional filter chain; firing Filter: 'SessionManagementFilter' 2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 11 of 12 in additional filter chain; firing Filter: 'ExceptionTranslationFilter' 2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password at position 12 of 12 in additional filter chain; firing Filter: 'FilterSecurityInterceptor' 2017-09-26 15:32:16,855 DEBUG o.s.security.web.FilterChainProxy - /error?grant_type=password reached end of additional filter chain; proceeding with original chain 2017-09-26 15:32:16,856 DEBUG o.s.s.w.c.HttpSessionSecurityContextRepository - SecurityContext is empty or contents are anonymous - context will not be stored in HttpSession. 2017-09-26 15:32:16,856 DEBUG o.s.s.w.a.ExceptionTranslationFilter - Chain processed normally 2017-09-26 15:32:16,856 DEBUG o.s.s.w.c.SecurityContextPersistenceFilter - SecurityContextHolder now cleared, as request processing completed
如何解决此问题?
问题与 Jersey配置有关 ,它正在窃取oauth2的请求,我不得不用重新配置它,@ApplicationPath("/ws") 因此配置现在看起来像:
@ApplicationPath("/ws")
@Configuration @ApplicationPath("/ws") public class JerseyConfig extends ResourceConfig { public JerseyConfig() { register(DawamService.class); } }
和我的webservice实现类:
@Component @Path("/dawam") public class DawamService extends DawamServiceBase { @GET @Produces({ MediaType.TEXT_HTML }) @Path("/test") public String getHTML() { System.out.println("##### Welcome to test webservice #########"); return "Welcome to test webservice"; } }