我已使用本指南(https://medium.com/emblatech/secure-your-spring-restful-apis-with-jwt-a-real-world-example-bfdd2679db5f)保护RestFull API。
但是现在当我尝试从REACT JS应用程序连接时遇到了CORS问题。
这是我的配置:
AuthorizationServerConfig
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Value("${security.jwt.client-id}")
private String clientId;
@Value("${security.jwt.client-secret}")
private String clientSecret;
@Value("${security.jwt.grant-type}")
private String grantType;
@Value("${security.jwt.grant-type-refresh}")
private String grantTypeRefresh;
@Value("${security.jwt.scope-read}")
private String scopeRead;
@Value("${security.jwt.scope-write}")
private String scopeWrite = "write";
@Value("${security.jwt.resource-ids}")
private String resourceIds;
@Autowired
private JwtAccessTokenConverter accessTokenConverter;
@Autowired
private AuthenticationManager authenticationManager;
@Qualifier("userDetailsServiceImpl")
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private DefaultTokenServices defaultTokenServices;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient(clientId)
.secret("{noop}"+clientSecret)
.authorizedGrantTypes(grantType, grantTypeRefresh)
.scopes(scopeRead, scopeWrite)
.resourceIds(resourceIds);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenServices(defaultTokenServices).authenticationManager(authenticationManager)
.accessTokenConverter(accessTokenConverter).userDetailsService(userDetailsService);
}
}
ResourceServerConfig
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
ResourceServerTokenServices tokenServices;
@Value("${security.jwt.resource-ids}")
private String resourceIds;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.resourceId(resourceIds).tokenServices(tokenServices);
}
@Override
public void configure(HttpSecurity http) throws Exception {
http
.requestMatchers()
.and()
.authorizeRequests()
.antMatchers("/actuator/**").permitAll()
.antMatchers("/oauth/**").authenticated();
}
}
SecurityConfig
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Value("${security.signing-key}")
private String signingKey;
@Value("${security.security-realm}")
private String securityRealm;
@Value("${security.jwt.token-validity-seconds}")
private int accessTokenValiditySeconds;
@Qualifier("userDetailsServiceImpl")
@Autowired
private UserDetailsService userDetailsService;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService)
.passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.STATELESS)
.and()
.httpBasic()
.realmName(securityRealm)
.and()
.csrf().disable();
}
@Override
@Bean
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@Bean
public JwtAccessTokenConverter accessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(signingKey);
return converter;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(accessTokenConverter());
}
@Bean
public TokenEnhancerChain tokenEnhancerChain() {
final TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
tokenEnhancerChain.setTokenEnhancers(Arrays.asList(new MyTokenEnhancer(), accessTokenConverter()));
return tokenEnhancerChain;
}
@Bean
@Primary
public DefaultTokenServices defaultTokenServices() {
DefaultTokenServices defaultTokenServices = new DefaultTokenServices();
defaultTokenServices.setTokenStore(tokenStore());
defaultTokenServices.setTokenEnhancer(tokenEnhancerChain());
defaultTokenServices.setSupportRefreshToken(true);
defaultTokenServices.setAccessTokenValiditySeconds(accessTokenValiditySeconds);
return defaultTokenServices;
}
private static class MyTokenEnhancer implements TokenEnhancer {
@Override
public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
// TODO Auto-generated method stub
return accessToken;
}
}
}
在每次通话中我都会收到此错误:
GET http://localhost:8080/test 401
Access to XMLHttpRequest at 'http://localhost:8080/test' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
我也已经尝试了一些解决方法,例如:How to configure CORS in a Spring Boot + Spring Security application?
但是对我没有任何作用。 有帮助吗?
答案 0 :(得分:1)
您需要将Cors Configuration添加到您的应用程序,以便它可以接受来自其他域的AJAX请求。不管这些请求是通过react还是angular或jquery发送的,服务器仍将以相同的方式运行。
在Spring Boot应用程序中接受CORS的最简单方法是在Controller类中添加以下注释:
@CrossOrigin(origins="*")
但是请注意,当您使用通配符(*)时,您的服务将接受来自任何域的不安全的Ajax请求。您可能希望将通配符替换为要接受其请求的特定域。
在所有控制器中重复注释可能很烦人并且容易出错。相反,您可以使用How to configure CORS in a Spring Boot + Spring Security application?中描述的一种配置解决方案,也可以遵循有关CORS configuration的Spring文档