我在我的应用程序中使用outh2实现了春季安全性,并且它在tomcat localhost和发送邮递员请求时都可以完美地工作。邮递员的要求如下:
Postman request part 1Postman request part 2
邮递员请求的响应:
{
"access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE1OTE2NjU0ODEsInVzZXJfbmFtZSI6ImNhbTF4IiwiYXV0aG9yaXRpZXMiOlsiREVMRVRFX1BSSVZJTEVHRSIsIlJFQURfUFJJVklMRUdFIiwiVVBEQVRFX1BSSVZJTEVHRSIsIkNSRUFURV9QUklWSUxFR0UiXSwianRpIjoiMjg3MDYzYzktZDUwZC00MTNjLTlkZGEtMTNkMTdlNDA2NTEwIiwiY2xpZW50X2lkIjoiY2xpZW50Q3JlZGVudGlhbHMiLCJzY29wZSI6WyJyZWFkIiwid3JpdGUiXX0.mS6hgKZXUX8ewVtEb7NHKwo8m6-Ehi3UE2Uw4ZnTazw",
"token_type": "bearer",
"refresh_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VyX25hbWUiOiJjYW0xeCIsInNjb3BlIjpbInJlYWQiLCJ3cml0ZSJdLCJhdGkiOiIyODcwNjNjOS1kNTBkLTQxM2MtOWRkYS0xM2QxN2U0MDY1MTAiLCJleHAiOjE1OTQyMTQyODEsImF1dGhvcml0aWVzIjpbIkRFTEVURV9QUklWSUxFR0UiLCJSRUFEX1BSSVZJTEVHRSIsIlVQREFURV9QUklWSUxFR0UiLCJDUkVBVEVfUFJJVklMRUdFIl0sImp0aSI6IjQxNGUzN2NjLWFhNWQtNDRmNS05ZGVhLWU4OTk3Y2FiZWQ1NiIsImNsaWVudF9pZCI6ImNsaWVudENyZWRlbnRpYWxzIn0.xhgqHbuCnYFjZQB0kBK8bGQs3-EiyWYeAg-pTYKuS78",
"expires_in": 43199,
"scope": "read write",
"jti": "287063c9-d50d-413c-9dda-13d17e406510"
}
但是当我尝试从另一个主机(响应应用程序)发送相同的请求时,我收到了错误消息。
响应登录呼叫:
async login(login, password) {
let cfg = {
auth: {
username: 'clientCredentials',
password: 'credentials'
}
};
let params = new URLSearchParams();
params.append('grant_type', 'password');
params.append('username', `${login}`);
params.append('password', `${password}`);
return axios.post(`${API_URL}/oauth/token`, params, cfg)
.then(response => {
if (response.data.accessToken) {
localStorage.setItem("user", JSON.stringify(response.data));
}
return response.data;
});
}
Spring安全性配置:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.antMatcher("/**")
.authorizeRequests()
.antMatchers("/oauth/token").permitAll()
.antMatchers("/login").permitAll()
.antMatchers("/logout").permitAll()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.logout();
}
Oauth2配置:
@Configuration
@EnableAuthorizationServer
@PropertySource("classpath:application-oauth2.properties")
public class OAuthConfiguration extends AuthorizationServerConfigurerAdapter {
private AuthenticationManager authenticationManager;
private BCryptPasswordEncoder passwordEncoder;
private UserDetailsService userDetailsService;
private Environment environment;
@Autowired
public OAuthConfiguration(@Qualifier("authenticationManagerBean") AuthenticationManager authenticationManager,
BCryptPasswordEncoder passwordEncoder, UserDetailsService userDetailsService,
Environment environment) {
this.authenticationManager = authenticationManager;
this.passwordEncoder = passwordEncoder;
this.userDetailsService = userDetailsService;
this.environment = environment;
}
@Bean
public TokenStore tokenStore() {
return new JwtTokenStore(defaultAccessTokenConverter());
}
@Bean
public JwtAccessTokenConverter defaultAccessTokenConverter() {
JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
converter.setSigningKey(SIGNING_KEY);
return converter;
}
@Override
public void configure(final AuthorizationServerSecurityConfigurer oauthServer) {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients
.inMemory()
.withClient("clientCredentials")
.secret(passwordEncoder.encode("credentials"))
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.scopes("read", "write")
.autoApprove(true)
.and()
.withClient("implicitClient")
.scopes("read", "write")
.authorizedGrantTypes("implicit")
.redirectUris("http://localhost:3000/")
.autoApprove(true)
.and()
.withClient(environment.getProperty(CLIENT_PROPERTY_KEY + "google.client-id"))
.secret(passwordEncoder.encode(
Objects.requireNonNull(environment.getProperty(CLIENT_PROPERTY_KEY + "google.client-secret")))
)
.authorizedGrantTypes("profile", "email")
.scopes("read", "write")
.autoApprove(true)
.and()
.withClient(environment.getProperty(CLIENT_PROPERTY_KEY + "facebook.client-id"))
.secret(passwordEncoder.encode(
Objects.requireNonNull(environment.getProperty(CLIENT_PROPERTY_KEY + "facebook.client-secret")))
)
.authorizedGrantTypes("profile", "email")
.scopes("read", "write")
.autoApprove(true);
}
@Override
public void configure(final AuthorizationServerEndpointsConfigurer endpoints) {
endpoints
.tokenStore(tokenStore())
.authenticationManager(authenticationManager)
.accessTokenConverter(defaultAccessTokenConverter())
.userDetailsService(userDetailsService);
}
}
简短错误日志:
Access is denied (user is anonymous); redirecting to authentication entry point
org.springframework.security.access.AccessDeniedException: Access is denied
怎么了?再说一遍,从tomcat或邮递员发送请求时,安全性没有问题,所以我建议React调用中有错误。感谢您的帮助:)
P.S。如果需要一些spring security impl来理解原因,我将其添加到问题中。
通过使用Pathfix可以简化整个过程,您不需要那么多代码,只需对API服务器进行简单的Rest调用就可以实现您想要的工作。