1. 程式人生 > >1 springboot的 springboot security OAuth的sso單點登入:

1 springboot的 springboot security OAuth的sso單點登入:

  • 整個工程包括三個獨立的應用,一個認證服務和兩個客戶端應用,結構非常簡單。

 Maven依賴

<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>



安全配置

客戶端的安全配置如下:

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

配置最核心的部分是 @EnableOAuth2Sso註解來開啟SSO。這裡要注意,我們需要重寫WebSecurityConfigurerAdapter 否則所有的路徑都會受到SSO的保護,這樣無論使用者訪問哪個頁面都會被重定向到登入頁面,在這個例子裡,index和login頁面是唯一不需要被防護的。

最後,我們定義一個RequestContextListener bean來處理request scopes。

application.yml:
server:
    port: 8082
    context-path: /ui
    session:
      cookie:
        name: UISESSION
security:
  basic:
    enabled: false
  oauth2:
    client:
      clientId: SampleClientId
      clientSecret: secret
      accessTokenUri: http://localhost:8081/auth/oauth/token
      userAuthorizationUri: http://localhost:8081/auth/oauth/authorize
    resource:
      userInfoUri: http://localhost:8081/auth/user/me
spring:
  thymeleaf:
    cache: false

說明:

  • 我們禁用了default Basic Authentication

  • accessTokenUri 是獲取訪問令牌的URL

  • userAuthorizationUri是授權使用者被重定向的目標URL

  • userInfoUri是使用者終端訪問使用者資訊的URL

在這個case裡,認證服務是我們自己建設的,但是在實際的應用場景下認證服務往往是第三方提供的比如Facebook 或者 gitHub



前端

前端並非本文的重點,這裡簡單提一下。客戶端有一個非常簡單的前端頁面
index.html:

<h1>Spring Security SSO</h1>

<a href="securedPage">Login</a>

securedPage.html:

<h1>Secured   Page</h1>

Welcome, <span th:text="${#authentication.name}">Name</span>
 

securedPage.html需要使用者通過授權才能訪問,如果一個未授權的使用者訪問這個頁面,他會被重定向到login頁面



3. 認證伺服器

3.1 Maven依賴

<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>

3.2 OAuth配置

本例中我們把AS(認證服務)器和RS放(資源伺服器)在一個例項中部署。

RS配置如下:

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

AS配置如下:

@Configuration
@EnableAuthorizationServer
public class AuthServerConfig 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("secret")
          .authorizedGrantTypes("authorization_code")
          .scopes("user_info")
          .autoApprove(true) ; 
    }
 
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager);
    }
}

這裡我們只開啟authorization_code授權模式,另外這裡注意到autoApprove=true,這意味著使用者不會被重定向到授權的頁面,也不需要手動給請求授權。

3.3 安全配置

這裡需要定義一個簡單的認證機制

@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 {
        auth.parentAuthenticationManager(authenticationManager)
          .inMemoryAuthentication()
          .withUser("john").password("123").roles("USER");
    }
}

注意,我們用了in-memory認證,這裡只是做一個簡單的例子,我們直接把賬號密碼寫到記憶體裡了,真正使用的時候這裡要換成自定義的userDetailsService.

3.4 使用者終端

一個很簡單的返回JSON訊息的介面

@RestController

public class UserController {

    @GetMapping("/user/me")

    public Principal user(Principal principal) {
        return principal;
    }

}

完整的程式碼下載連結:Over On Github



作者:半夜菊花茶
連結:https://www.jianshu.com/p/d94bb118aa43
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。