简体   繁体   English

Spring Security-实现OAuth2 SSO

[英]Spring security - implement oauth2 sso

I want to implement central authentication system with spring security and oauth2 sso . 我想用spring security和oauth2 sso实现中央身份验证系统 In other words, I have a spring boot application that is responsible for authorization and one simple client. 换句话说,我有一个负责授权的spring boot应用程序和一个简单的客户端。 My client has rest API. 我的客户有rest API。 First I get token from the authorization server, then send a request to client API with an authorization header contains bearer token from above request. 首先,我从授权服务器获取令牌,然后将请求发送到客户端API,其中授权标头包含上述请求中的承载令牌。 But this request always gets me server login page . 但是这个请求总是让我进入服务器登录页面

Here is the implementation of the server and the client: 这是服务器和客户端的实现:

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

First, I send client_id and secret code along side with username, password and grant_type to localhost:8900/auth/oauth/token and get a result like this: 首先,我将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"
}

Now, I pickup above token and send a request to localhost:9000/client1/admin with header contains above token. 现在,我拾取了上面的令牌,并向标头包含上面的令牌的localhost:9000/client1/admin发送了一个请求。 But it seems the client application ignores the header and shows server login page as result. 但是似乎客户端应用程序会忽略标题,并显示服务器登录页面作为结果。 How can I fix this problem? 我该如何解决这个问题?

@EnableOAuth2Sso is an annotation for using OAuth 2.0 as an end-user authentication mechanism (eg "A Login with Google" button). @EnableOAuth2Sso是用于将OAuth 2.0用作最终用户身份验证机制的注释(例如,“使用Google登录”按钮)。 This annotation is wiring your app to redirect to a login page on your authorization server where you would log in and then get redirected back to your app. 此注释链接您的应用程序以重定向到授权服务器上的登录页面,您将在该页面上登录然后重定向回您的应用程序。

If this is your intent, then you'll need to update your Authorization Server to support the authorization_code grant flow instead of the password grant flow. 如果这是您的意图,那么您需要更新授权服务器以支持authorization_code授予流程,而不是password授予流程。

However, if your client is strictly a REST API, then you are more likely to need to wire the client using @EnableResourceServer instead of @EnableOAuth2Sso . 但是,如果您的客户端严格来说是REST API,则您更有可能需要使用@EnableResourceServer而不是@EnableOAuth2Sso@EnableResourceServer客户端。 A Resource Server is what takes a token as authorization, via the Authorization HTTP header. 资源服务器通过授权HTTP标头将令牌作为授权。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM