Spring 安全 - 实施 oauth2 sso
Spring security - implement oauth2 sso
我想实施 具有 spring 安全性和 oauth2 sso 的中央身份验证系统。换句话说,我有一个 spring 负责授权的启动应用程序和一个简单的客户端。我的客户休息 API。首先,我从授权服务器获取令牌,然后向客户端 API 发送请求,授权 header 包含来自上述请求的不记名令牌。但是这个请求总是让我 服务器登录页面 .
这里是服务端和客户端的实现:
Server
AuthorizationServerConfig.java
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("SampleClientId")
.secret("{noop}secret")
.authorizedGrantTypes("password")
.scopes("user_info")
.autoApprove(true);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(this.authenticationManager);
}
ApplicationConfig:
@SpringBootApplication
@EnableResourceServer
public class ApplicationConfig extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(ApplicationConfig.class, args);
}
}
SecurityConfig:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//this is just example
auth.inMemoryAuthentication().withUser("user").password("{noop}1234").roles("user");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers("/login", "/oauth/authorize", "/oauth/token")
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().permitAll();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
application.yml:
server:
port: 8900
servlet:
context-path: /auth
Client:
ApplicationConfig:
@SpringBootApplication
public class ApplicationConfig {
public static void main(String[] args) {
SpringApplication.run(ApplicationConfig.class, args);
}
}
SecurityConfig:
@Configuration
@EnableOAuth2Sso
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/", "/login**")
.permitAll()
.anyRequest()
.authenticated();
}
}
TestController:
@RestController
public class HomeController {
@GetMapping("/")
public String index() {
return "home";
}
@RequestMapping("/admin")
public String admin() {
return "admin";
}
}
application.yml:
server:
port: 9000
servlet:
context-path: /client1
security:
basic:
enabled: false
oauth2:
client:
clientId: SampleClientId
clientSecret: secret
accessTokenUri: http://localhost:8900/auth/oauth/token
userAuthorizationUri: http://localhost:8900/auth/oauth/authorize
resource:
userInfoUri: http://localhost:8900/auth/user/me
首先,我将 client_id 和密码连同用户名、密码和 grant_type 一起发送到 localhost:8900/auth/oauth/token
并得到如下结果:
{
"access_token": "603b505f-e701-43d0-b8b8-976a2178f7ea",
"token_type": "bearer",
"expires_in": 43199,
"scope": "user_info"
}
现在,我拿起上面的令牌并向 localhost:9000/client1/admin
发送请求
with header 包含上述标记。但客户端应用程序似乎忽略了 header 并显示服务器登录页面作为结果。我该如何解决这个问题?
@EnableOAuth2Sso
是使用 OAuth 2.0 作为 end-user 身份验证机制的注释(例如 "A Login with Google" 按钮)。此注释将您的应用程序连接到您的授权服务器上的登录页面,您将在其中登录然后重定向回您的应用程序。
如果这是您的意图,那么您需要 update your Authorization Server to support the authorization_code
grant flow 而不是 password
资助流程。
但是,如果您的客户端严格来说是 REST API,那么您更有可能需要使用 @EnableResourceServer
而不是 @EnableOAuth2Sso
连接客户端。 A Resource Server 是通过授权 HTTP header.
将令牌作为授权的方式
我想实施 具有 spring 安全性和 oauth2 sso 的中央身份验证系统。换句话说,我有一个 spring 负责授权的启动应用程序和一个简单的客户端。我的客户休息 API。首先,我从授权服务器获取令牌,然后向客户端 API 发送请求,授权 header 包含来自上述请求的不记名令牌。但是这个请求总是让我 服务器登录页面 .
这里是服务端和客户端的实现:
Server
AuthorizationServerConfig.java
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
oauthServer
.tokenKeyAccess("permitAll()")
.checkTokenAccess("isAuthenticated()");
}
@Override
public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
clients.inMemory()
.withClient("SampleClientId")
.secret("{noop}secret")
.authorizedGrantTypes("password")
.scopes("user_info")
.autoApprove(true);
}
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
endpoints.authenticationManager(this.authenticationManager);
}
ApplicationConfig:
@SpringBootApplication
@EnableResourceServer
public class ApplicationConfig extends SpringBootServletInitializer {
public static void main(String[] args) {
SpringApplication.run(ApplicationConfig.class, args);
}
}
SecurityConfig:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
//this is just example
auth.inMemoryAuthentication().withUser("user").password("{noop}1234").roles("user");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.requestMatchers()
.antMatchers("/login", "/oauth/authorize", "/oauth/token")
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin().permitAll();
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
application.yml:
server:
port: 8900
servlet:
context-path: /auth
Client:
ApplicationConfig:
@SpringBootApplication
public class ApplicationConfig {
public static void main(String[] args) {
SpringApplication.run(ApplicationConfig.class, args);
}
}
SecurityConfig:
@Configuration
@EnableOAuth2Sso
public class ApplicationSecurityConfig extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.csrf().disable()
.authorizeRequests()
.antMatchers("/", "/login**")
.permitAll()
.anyRequest()
.authenticated();
}
}
TestController:
@RestController
public class HomeController {
@GetMapping("/")
public String index() {
return "home";
}
@RequestMapping("/admin")
public String admin() {
return "admin";
}
}
application.yml:
server:
port: 9000
servlet:
context-path: /client1
security:
basic:
enabled: false
oauth2:
client:
clientId: SampleClientId
clientSecret: secret
accessTokenUri: http://localhost:8900/auth/oauth/token
userAuthorizationUri: http://localhost:8900/auth/oauth/authorize
resource:
userInfoUri: http://localhost:8900/auth/user/me
首先,我将 client_id 和密码连同用户名、密码和 grant_type 一起发送到 localhost:8900/auth/oauth/token
并得到如下结果:
{
"access_token": "603b505f-e701-43d0-b8b8-976a2178f7ea",
"token_type": "bearer",
"expires_in": 43199,
"scope": "user_info"
}
现在,我拿起上面的令牌并向 localhost:9000/client1/admin
发送请求
with header 包含上述标记。但客户端应用程序似乎忽略了 header 并显示服务器登录页面作为结果。我该如何解决这个问题?
@EnableOAuth2Sso
是使用 OAuth 2.0 作为 end-user 身份验证机制的注释(例如 "A Login with Google" 按钮)。此注释将您的应用程序连接到您的授权服务器上的登录页面,您将在其中登录然后重定向回您的应用程序。
如果这是您的意图,那么您需要 update your Authorization Server to support the authorization_code
grant flow 而不是 password
资助流程。
但是,如果您的客户端严格来说是 REST API,那么您更有可能需要使用 @EnableResourceServer
而不是 @EnableOAuth2Sso
连接客户端。 A Resource Server 是通过授权 HTTP header.