1. 程式人生 > >Spring Security OAuth2 實現SSO

Spring Security OAuth2 實現SSO

SSO即Single Sign-On,單點登入,即授權伺服器形式,通過在一個網站上登入完後,給予過授權的就可以直接用這個帳號資訊登入了,類似於qq微信登入其他APP。
本篇文章,將利用Spring Security實現簡單的單點登入中需要的,認證伺服器和客戶端。

SSO伺服器

首先實現一個SSO伺服器,下面是基本的pom檔案:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId
>
</dependency> <dependency> <groupId>org.springframework.security.oauth</groupId> <artifactId>spring-security-oauth2</artifactId> </dependency>

啟動main方法:
這裡面主要用EnableResourceServer來開啟資源伺服器。

@SpringBootApplication
@EnableResourceServer public class SsoServerApplication { public static void main(String[] args) { SpringApplication.run(SsoServerApplication.class, args); } }

下面再分別介紹Spring Security和OAuth2的Config類:
以下是OAuth2的Config類:

//Auth2的配置檔案
@Configuration
@EnableAuthorizationServer
public
class Auth2Config extends AuthorizationServerConfigurerAdapter { @Autowired private AuthenticationManager authenticationManager; //使用預設的認證管家 @Override public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception { oauthServer.tokenKeyAccess("permitAll()") //能夠獲取token的 .checkTokenAccess("isAuthenticated()"); //檢測是否認證 } @Override public void configure(final ClientDetailsServiceConfigurer clients) throws Exception { clients.inMemory() .withClient("SampleClientId") //接受的clientId .secret("secret") //預設secret .authorizedGrantTypes("authorization_code") //授權模式 .scopes("user_info") //範圍,只獲取使用者認證。 .autoApprove(true); } @Override public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception { endpoints.authenticationManager(authenticationManager); } }

Auth2Config 定義了一些Auth2的資訊,例如對名為SampleClientId的註冊,以及對認證規則的定義:

oauthServer.tokenKeyAccess("permitAll()")         //能夠獲取token的
                .checkTokenAccess("isAuthenticated()");     //檢測是否認證

以下是Spring Security的配置:

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private AuthenticationManager authenticationManager;

    @Override
    protected void configure(HttpSecurity http) throws Exception { 
        http.requestMatchers()
                .antMatchers("/login", "/oauth/authorize")
                .and()
                .authorizeRequests()    //請求授權,後面的需要授權。
                .anyRequest()
                .authenticated()
                .and()
                .formLogin()             //登入表單開放給所有人,預設的登入表單。
                .permitAll();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception { // @formatter:off
        auth.parentAuthenticationManager(authenticationManager)
                .inMemoryAuthentication()
                .withUser("anla7856")     //模擬一個註冊使用者名稱
                .password("123456")
                .roles("USER");
    }
}

下面是application.yml配置:

server:
  port: 8080
  context-path: /auth
security:
  basic:
    enabled: false          #阻止基本認證

下面是sso客戶端程式碼:

SSO客戶端

sso客戶端,也是基於Spring Security實現,下面是其pom檔案:

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
        </dependency>

        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity4</artifactId>
        </dependency>

再看看啟動Application類:

@SpringBootApplication
public class SsoClientApplication {
    @Bean
    public RequestContextListener requestContextListener() {
        return new RequestContextListener();
    }                 //自定義一個RequestContextListener

    public static void main(String[] args) {
        SpringApplication.run(SsoClientApplication.class, args);
    }
}

接下來是Spring Security的配置檔案:

@EnableOAuth2Sso
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**")
                .authorizeRequests()
                .antMatchers("/", "/login**")
                .permitAll()
                .anyRequest()
                .authenticated();
    }
}

下面是 WebMvcConfig:

@Configuration
@EnableWebMvc
public class WebConfig extends WebMvcConfigurerAdapter {
    @Bean
    public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
        return new PropertySourcesPlaceholderConfigurer();
    }

    @Override
    public void configureDefaultServletHandling(final DefaultServletHandlerConfigurer configurer) {
        configurer.enable();      //使配置生效
    }

    /**
     * 配置view
     * @param registry
     */
    @Override
    public void addViewControllers(final ViewControllerRegistry registry) {
        super.addViewControllers(registry);
        registry.addViewController("/")
                .setViewName("forward:/index");
        registry.addViewController("/index");
        registry.addViewController("/securedPage");
    }

    /**
     * 對映資原始檔
     * @param registry
     */
    @Override
    public void addResourceHandlers(final ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/resources/**")
                .addResourceLocations("/resources/");
    }
}

application.yml檔案:

server:
    port: 8989
    session:
      cookie:
        name: UI2SESSION
security:
  basic:
    enabled: false
  oauth2:
    client:
      clientId: SampleClientId      #與server端對應
      clientSecret: secret          #與服務端對應
      accessTokenUri: http://localhost:8080/auth/oauth/token
      userAuthorizationUri: http://localhost:8080/auth/oauth/authorize
    resource:
      userInfoUri: http://localhost:8080/auth/door/me     #資源伺服器,即對sso server的資源訪問。
spring:
  thymeleaf:
    cache: false

整體的架構也算搭好了,server端和client端都是用Spring Security,當用戶訪問client的頁面時,由Spring Security控制,會使其跳轉到sso Server端的預設login頁面進行驗證,也就是在Server端配置好的clientid,當驗證使用者名稱密碼通過時,返回給給客戶端,此時客戶端從security.oauth2.resource.userInfoUri的資源伺服器下獲取相應的資源。