Java Spring Security:401 令牌 OAuth2 端点未经授权 [英] Java Spring Security: 401 Unauthorized for token OAuth2 end point
问题描述
我的 Spring Boot 项目中有一个相当基本的设置.我正在尝试设置 OAuth2 来保护我的 API,但我遇到了 /oauth/token
端点的问题.向我的 /oauth/token
端点发出 POST 或 GET 请求会导致以下响应(带有 401 Unauthorized
状态代码):
I have a fairly basic setup in my Spring Boot project. I'm trying to set up OAuth2 to protect my API but I'm running into issues with my /oauth/token
end point. Making either a POST or GET request to my /oauth/token
end point results in the following response (With a 401 Unauthorized
status code):
{
"timestamp": "2018-09-17T16:46:59.961+0000",
"status": 401,
"error": "Unauthorized",
"message": "Unauthorized",
"path": "/oauth/token"
}
这是我的授权服务器配置.
This is my Authorization server configuration.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
import org.springframework.security.oauth2.provider.token.TokenStore;
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private TokenStore tokenStore;
@Autowired
private UserApprovalHandler userApprovalHandler;
@Autowired
@Qualifier("authenticationManagerBean")
private AuthenticationManager authenticationManager;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("client_id")
.secret("secret")
.authorizedGrantTypes("password", "authorization_code", "refresh_token")
.scopes("read", "write")
.accessTokenValiditySeconds(600)
.refreshTokenValiditySeconds(3600);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.tokenStore(this.tokenStore)
.userApprovalHandler(this.userApprovalHandler)
.authenticationManager(this.authenticationManager);
}
@Override
public void configure(AuthorizationServerSecurityConfigurer security) {
security.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()")
.passwordEncoder(this.passwordEncoder);
}
}
这是我的资源服务器配置.还没有什么重要的:
This is my resource server configuration. Nothing significant yet:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
@Autowired
private TokenStore tokenStore;
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
resources.tokenStore(this.tokenStore);
}
}
最后是我的标准网络安全配置:
And finally my standard web security configuration:
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.approval.ApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenApprovalStore;
import org.springframework.security.oauth2.provider.approval.TokenStoreUserApprovalHandler;
import org.springframework.security.oauth2.provider.approval.UserApprovalHandler;
import org.springframework.security.oauth2.provider.request.DefaultOAuth2RequestFactory;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore;
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private ClientDetailsService clientDetailsService;
@Autowired
public void globalUserDetails(AuthenticationManagerBuilder builder) throws Exception {
builder.inMemoryAuthentication()
.withUser("user").password("password").roles("ADMIN")
.and()
.withUser("admin").password("password").roles("USER");
}
@Override
protected void configure(HttpSecurity security) throws Exception {
security.csrf().disable()
.anonymous().disable()
.authorizeRequests()
.antMatchers("/oauth/token").permitAll();
}
@Override
@Bean
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Bean
public TokenStore tokenStore() {
return new InMemoryTokenStore();
}
@Bean
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder(8);
}
@Bean
@Autowired
public UserApprovalHandler userApprovalHandler(TokenStore tokenStore) {
TokenStoreUserApprovalHandler handler = new TokenStoreUserApprovalHandler();
handler.setTokenStore(tokenStore);
handler.setRequestFactory(new DefaultOAuth2RequestFactory(this.clientDetailsService));
handler.setClientDetailsService(this.clientDetailsService);
return handler;
}
@Bean
@Autowired
public ApprovalStore approvalStore(TokenStore tokenStore) {
TokenApprovalStore store = new TokenApprovalStore();
store.setTokenStore(tokenStore);
return store;
}
}
我已经用不同的匹配器模式搞砸了很多,看看我是否可以让它工作,但我没有任何运气.我在 http://localhost:8080
上的根上下文和 servlet 路径中运行它.
I've messed around quite a bit with different matcher patterns to see if I can get it working but I haven't had any luck. I'm running this in a root context and servlet path on http://localhost:8080
.
我可以确认,当 Spring Boot 启动并试图达到预期的 404 时,终点已映射到输出中并尝试达到略有不同的终点.
I can confirm that the end point is mapped in the output when Spring Boot fires up and trying to hit a slightly different end point results in an expected 404.
推荐答案
事实证明我没有正确到达终点.我通过 HTTP POST 发送了我的所有数据,包括客户端凭据.
Turns out I wasn't hitting the end point correctly. I was sending all of my data, client credentials included, via HTTP POST.
POST http://localhost:8080/oauth/token
...
client_id=client_id&secret=secret&scope=read&grant_type=password&username=user&password=password
我需要使用 HTTP 基本身份验证来发送我的客户端凭据而不是发布它们:
I needed to use HTTP Basic Auth to send my client credentials rather than POSTing them:
POST http://localhost:8080/oauth/token
Authorization: Basic Y2xpZW50X2lkOnNlY3JldA==
...
scope=read&grant_type=password&username=user&password=password
这篇关于Java Spring Security:401 令牌 OAuth2 端点未经授权的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!