在项目中,我想使用spring-security-jwt-1.0.9.RELEASE,为此我编写了以下代码:
CORSFilter.java
public class CORSFilter implements Filter {
@Override
public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
HttpServletResponse response = (HttpServletResponse) servletResponse;
response.setHeader("Access-Control-Max-Age", "3600");
response.setHeader("Access-Control-Allow-Origin", "*");
response.setHeader("Access-Control-Allow-Credentials", "true");
response.setHeader("Access-Control-Allow-Methods", "POST, GET, PUT, OPTIONS, DELETE");
response.setHeader("Access-Control-Allow-Headers", "X-Requested-With, Content-Type, Authorization, Origin, Accept, Access-Control-Request-Method, Access-Control-Request-Headers");
if ("OPTIONS".equalsIgnoreCase(((HttpServletRequest) servletRequest).getMethod())) {
response.setStatus(HttpServletResponse.SC_OK);
} else {
filterChain.doFilter(servletRequest, response);
}
}
@Override
public void init(FilterConfig filterConfig) {
}
@Override
public void destroy() {
}
}
FindDoctorApiConfiguration.java
@Configuration
@EnableWebMvc
@ComponentScan(basePackages = "ir.shaingroup.FindDoctorAPI")
public class FindDoctorApiConfiguration extends WebMvcConfigurationSupport {
@Override
protected void addResourceHandlers(ResourceHandlerRegistry registry) {
registry.addResourceHandler("/resources/**").addResourceLocations("/resources/");
}
@Bean(name = "messageSource")
public ResourceBundleMessageSource resourceBundleMessageSource() {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setBasename("i18n/lang");
messageSource.setDefaultEncoding("UTF-8");
messageSource.setUseCodeAsDefaultMessage(true);
return messageSource;
}
}
FindDoctorApiInitializer.java
public class FindDoctorApiInitializer extends AbstractAnnotationConfigDispatcherServletInitializer {
@Override
protected Class<?>[] getRootConfigClasses() {
return new Class[] { FindDoctorApiConfiguration.class };
}
@Override
protected Class<?>[] getServletConfigClasses() {
return null;
}
@Override
protected String[] getServletMappings() {
return new String[] { "/" };
}
@Override
protected Filter[] getServletFilters() {
return new Filter[] { new CORSFilter() };
}
}
SpringSecurityConfig.java
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter {
private final ClientDetailsService clientDetailsService;
@Autowired
public SpringSecurityConfig(ClientDetailsService clientDetailsService) {
this.clientDetailsService = clientDetailsService;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.inMemoryAuthentication()
.withUser("user").password("123").roles("USER")
.and()
.withUser("admin").password("123").roles("ADMIN")
.and()
.withUser("doctor").password("123").roles("DOCTOR")
;
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("**/oauth/**").permitAll()
.anyRequest().authenticated()
.and()
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.csrf().disable()
.anonymous().disable()
;
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
@Bean
public UserDetailsService userDetailsServiceBean() throws Exception {
return super.userDetailsServiceBean();
}
@Bean
@Autowired
public TokenStoreUserApprovalHandler userApprovalHandler(TokenStore tokenStore) {
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setClientDetailsService(clientDetailsService);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(clientDetailsService));
return handler;
}
}
AuthorizationServerConfig.java
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
private static final String publicKey = "-----BEGIN PUBLIC KEY-----\n" +
"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAupPVZSSdjwwLiSxkquhS\n" +
"Udwohh5AiiGxiNUTmCgu+0P7hF5kvrhl+Gm8pTD+Svf5LCZ/uZQeYeND/M9QzCw8\n" +
"RQZe1kCCwYW0cvNovyXTq37sJM+X5btGHRFOW3hHuHlaar02aPhNdfoULkNUBS0b\n" +
"h06HemJkv0+pHJ/FjVKu4BycBrMnvwtMhF2kcQCZCJk8HfiPbpLt03YiRkGX3wiR\n" +
"B9OOMIh5MQQWO/oi5xPvoiXVxBKAaER5QQ+OkGyTgqKM/VMlMqB43ncchTCn2+ZY\n" +
"9wx5KYWgr87nsTAXDTnWxhe49Fx5hPgfyrhqg4ZC+w/2qQcbBpeEA6nFjDviZfiJ\n" +
"2QIDAQAB\n" +
"-----END PUBLIC KEY-----";
private static final String privateKey = "-----BEGIN RSA PRIVATE KEY-----\n" +
"MIIEowIBAAKCAQEAupPVZSSdjwwLiSxkquhSUdwohh5AiiGxiNUTmCgu+0P7hF5k\n" +
"vrhl+Gm8pTD+Svf5LCZ/uZQeYeND/M9QzCw8RQZe1kCCwYW0cvNovyXTq37sJM+X\n" +
"5btGHRFOW3hHuHlaar02aPhNdfoULkNUBS0bh06HemJkv0+pHJ/FjVKu4BycBrMn\n" +
"vwtMhF2kcQCZCJk8HfiPbpLt03YiRkGX3wiRB9OOMIh5MQQWO/oi5xPvoiXVxBKA\n" +
"aER5QQ+OkGyTgqKM/VMlMqB43ncchTCn2+ZY9wx5KYWgr87nsTAXDTnWxhe49Fx5\n" +
"hPgfyrhqg4ZC+w/2qQcbBpeEA6nFjDviZfiJ2QIDAQABAoIBAQCLCvDU11yz5f4S\n" +
"1AqRc2ElsDRi/tiKGGH93w0jL48Toa4nD1F08GbNob78PG7F39bJmEdHPaMGwB9C\n" +
"oB1Oiwi/R+gVMy4+mi3IHK3LBZ2hCI1jQXGpus6divAiKpkIWSeQtEGAKMtRSHUR\n" +
"pQtQcDU7uMIt6nW6PNuCgW7vytaYHHN4xqeseUowaSa0x+9arlhpM2D7PnBVt+PN\n" +
"anl1x3vNNFXmLqHotGY4ZiiG4Vkb4OY1JAMPb6w0YbGaGqEz87b+kaUJdOzGeU/n\n" +
"Fy/sdsFI5CfZirP0H628w/iurK9eRcHivvgieZKeLailTnJMnmGl5LrkNGsZAHn2\n" +
"sxgAVPwBAoGBAOqsurjFy30RmFo3LxJ0XLVG/w7OJ6AbF5gIe1+oflG/SPLGKqxo\n" +
"NV09YaTIfQfAfrHpyykWuAUS33QY7AuY4dRYbcSnHo9zQWrCiBl6pXJhquOuoIDZ\n" +
"QBvFXGkMtdsYnkKmbj4Sbly/DJZWN9Llypakue5WgZeMdGmxg0K3kwKpAoGBAMuI\n" +
"NhKJiP17TrVgBsI8W3T6jkTLsmcm0bi3jmmxRcM4sKp0yK+vvZPmlk6qwtn5axTP\n" +
"HOdsdIh0ZP3DzDPNoc0jJwZqPpOws9Y9Zo8dlLG//5U9k2kPGy2POu6F1XgI8e8x\n" +
"tI84vufyoscJVTDqibFYF38UumNRHVuQruby+PuxAoGAEXlrLfcMf/OfdJhHWQhx\n" +
"Hs56j4+qQ7HAwAFhrm3NeijUNb+rzcq0royziKGlLb6XsIfIKPcYHMia+vogGXz4\n" +
"0+cBxXLsQ6JBbMGvgLYxO6MqJmoKaY3DyE2Z4/ieUgIzRqM98kFNFnrjZQ5meb3C\n" +
"qBT8A1NNswsyX+xn6b/hooECgYBzFNF+KcYLjW0zoNgxe2869XD79TEqoghzKVac\n" +
"7F9FwwghWWcf736B4h+a23LRTPX/DhyJvgkmHqn70nnj0KFsHDQ0rF41o/QLbyxO\n" +
"P6uT1bvt5qMzBBeZ6yKnO4U4GdayKKivUqae/9KKN/yza+nvHKAsesvo3DR9UZGT\n" +
"hE7EAQKBgDTAdeIqFFXsnjWAIl8gvYDbmZA+oBT5dNAHLAIxuVns42IknxHUPjHd\n" +
"78q4VNRGGtMlxXJMJ9pwKdR1BRa4vbiloUZJqaDgU0qLkUtQ1/NE16LTuFI5B3gl\n" +
"/d9d4AyW8kgd0fiJn5DQlLOAYJ4eU8XosjQNLh4YSHiQS7CBII6o\n" +
"-----END RSA PRIVATE KEY-----";
private final AuthenticationManager authenticationManager;
@Autowired
public AuthorizationServerConfig(@Qualifier("authenticationManagerBean") AuthenticationManager authenticationManager) {
this.authenticationManager = authenticationManager;
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()").allowFormAuthenticationForClients();
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("FindDoctorApiAdmin")
.secret("secret")
.scopes("read", "write", "user", "doctor", "admin")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.accessTokenValiditySeconds(3600)
.refreshTokenValiditySeconds(2592000)
.and()
.withClient("FindDoctorApiDoctor")
.secret("secret")
.scopes("read", "write", "doctor")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.accessTokenValiditySeconds(3600)
.refreshTokenValiditySeconds(2592000)
.and()
.withClient("FindDoctorApiUser")
.secret("secret")
.scopes("read", "write", "user")
.authorizedGrantTypes("password", "authorization_code", "refresh_token", "implicit")
.authorities("ROLE_CLIENT", "ROLE_TRUSTED_CLIENT")
.accessTokenValiditySeconds(3600)
.refreshTokenValiditySeconds(2592000)
;
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(customTokenEnhancer(), accessTokenConverter()));
endpoints.prefix("/FindDoctorAPI")
.tokenStore(tokenStore())
.tokenEnhancer(tokenEnhancerChain)
.accessTokenConverter(accessTokenConverter())
.authenticationManager(authenticationManager);
}
@Bean
@Primary
public DefaultTokenServices tokenServices() {
final DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setSupportRefreshToken(true);
return defaultTokenServices;
}
@Bean
public CustomTokenEnhancer customTokenEnhancer() {
return new CustomTokenEnhancer();
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(privateKey);
converter.setVerifierKey(publicKey);
return converter;
}
@Bean
public JwtTokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
}
ResourceServerConfig.java
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
private static final String RESOURCE_ID = "my_rest_api";
private final AccessDeniedHandler accessDeniedHandler;
@Autowired
public ResourceServerConfig(AccessDeniedHandler accessDeniedHandler) {
this.accessDeniedHandler = accessDeniedHandler;
}
@Override
public void configure(ResourceServerSecurityConfigurer resources) {
resources
.stateless(false)
.resourceId(RESOURCE_ID)
;
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.anonymous().disable()
.requestMatchers()
.antMatchers("**/rest/user/**")
.antMatchers("**/rest/admin/**")
.antMatchers("**/rest/doctor/**")
.and()
.authorizeRequests()
.antMatchers("**/rest/user/**").access("hasRole('USER')")
.antMatchers("**/rest/admin/**").access("hasRole('ADMIN')")
.antMatchers("**/rest/doctor/**").access("hasRole('DOCTOR')")
.and()
.exceptionHandling()
.accessDeniedHandler(accessDeniedHandler)
;
}
}
现在,当我输入下面的地址来获取token_access时,我会遇到线程中包含的消息。
post --- http://localhost:8001/FindDoctorAPI/oauth/token?grant_type=password&username=user&password=123
我搜索了很多网站,但所有解决方案都没有解决我的问题。 请给我一些指导,并告诉我问题出在哪里???