SpringCloud-OAuth2結合zuul實現SSO

前言

爬了兩天的坑終於上來了,看別人寫的很簡單,本身寫的時候就各類問題,網上SSO文章不少,寫的時候就各類問題(本身太菜了)。記錄一下,之後方便查看。html

關於OAuth2認證和受權服務器見上一篇java

https://zheyday.github.io/2019/10/07/SpringCloud-OAuth2%E5%92%8CJWT/git

<font color=#0099ff>項目地址</font>github

https://github.com/zheyday/SpringCloudStudy 使用git工具算法

git checkout sso

參考資料:spring

http://www.javashuo.com/article/p-cniijmfd-p.html瀏覽器

阮一峯OAuth2講解 http://www.javashuo.com/article/p-cvinqsjv-ma.html服務器

什麼是SSO

英文全稱single Sign On,中文名單點登陸。就是在多應用系統中,用戶只須要登陸一次就能夠訪問全部信任服務。SSO經過將用戶登錄信息映射到瀏覽器cookie中,解決其餘服務免登錄獲取用戶session的問題。cookie

大致框架

項目中一個有5個模塊:session

  • oauth-server是認證和受權服務,負責令牌的發放

  • zuul是網關服務,實現統一受權

  • eureka-client和eureka-client1是兩個應用服務

  • eureka-server-single是eureka註冊中心

要實現的功能就是經過zuul端口訪問eureka-client,首次須要登陸,而後內部跳轉到oauth-server中進行認證和受權,成功以後也能夠不用登陸訪問eureka-client1。

oauth-server

詳見

https://zheyday.github.io/2019/10/07/SpringCloud-OAuth2%E5%92%8CJWT/

更改了幾個地方

AuthorizationServerConfig

@Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
                .withClient("zuul")
                .secret(new BCryptPasswordEncoder().encode("secret"))
                .scopes("app")
                .authorizedGrantTypes("authorization_code", "password")
                .redirectUris("http://localhost:9110/login")
        ;
//        clients.withClientDetails(new JdbcClientDetailsService(dataSource));
    }

UserController

這個函數能夠爲其餘模塊資源服務器提供校驗

@RestController
@RequestMapping("/oauth2_token")
public class UserController {
    @GetMapping("/current")
    public Principal user(Principal principal) {
        return principal;
    }
}

ResourceServerConfig

@Override
    public void configure(HttpSecurity http) throws Exception {
        http
//                antMatcher表示只能處理/oauth2_token的請求
                .antMatcher("/oauth2_token/**")
                .authorizeRequests()
                .anyRequest().authenticated()
        ;
    }

application.yml

添加了根地址,也就是每次訪問這個服務都要加上 /oauth-server

server:
  port: 9120
#  url根地址 不配置的話會報invalid_token錯誤
#  或者在zuul中配置也能夠
  servlet:
    context-path: /oauth-server

Zuul

zuul做爲系統的入口,提供路由、統一受權等功能。

依賴見項目中

<font color='red'>注意:全部模塊都引入了spring-cloud-starter-oauth2依賴,因此放入了項目的公共pom.xml中,實現oauth2只須要引用這一個就能夠</font>

application.yml

貼出主要配置,詳細見項目中

sensitiveHeaders:這個必需要。zuul在轉發路由時,會改寫request中的頭部信息,設置成空就是不過濾

security.oauth2.resource:這個是和解析令牌相關的配置

資源服務器須要解析令牌驗證正確性,方式有三種:

  1. 若是令牌不是jwt非對稱加密,那麼訪問/oauth/check_token直接驗證token; 若是是非對稱,訪問/oauth/token_key得到公鑰進行解析
  2. 訪問認證服務器中的controller中的方法,得到Principal進行驗證
  3. 在資源服務器本地配置,繼承ResourceServerConfigurerAdapter接口,實現和認證服務器相同的加密方式
zuul:
  routes:
    eureka-client:
      path: /eureka-client/**
      sensitiveHeaders:
      serviceId: eureka-client
    eureka-client1:
      path: /eureka-client1/**
      sensitiveHeaders:
      serviceId: eureka-client1
    oauth-server:
      path: /oauth-server/**
      sensitiveHeaders:
        serviceId: eureka-client
#認證服務器地址
oauth-server: http://localhost:9120/oauth-server
security:
  oauth2:
#   和認證服務器中的client設置對應  
    client:
	  client-id: zuul
      client-secret: secret
#	   獲取令牌地址
      access-token-uri: ${oauth-server}/oauth/token
#      認證地址
      user-authorization-uri: ${oauth-server}/oauth/authorize
    resource:
#      進行令牌校驗
#      1、訪問controller獲取Principal
#      user-info-uri: ${oauth-server}/oauth2_token/current
#      prefer-token-info: false
#      2、訪問受權服務器獲取公鑰 解析令牌
      jwt:
        key-uri: ${oauth-server}/oauth/token_key

配置WebSecurityConfig

整個zuul模塊只要添加這一個配置就能夠

@EnableOAuth2Sso
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
        //須要受權的url    
                .authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and().csrf().disable()
        ;
    }
}

eureka-client(資源服務器)

application.yml

新添以下,用於驗證請求的令牌是否正確

security:
  oauth2:
    resource:
      id: eureka-client
      #      資源服務器三種驗證令牌方法
      #       1、在ResourceServerConfig中本地配置
      #      2、從認證服務器獲取用戶信息 解析出token
      #      user-info-uri: ${oauth-server}/oauth2_token/current
      #      prefer-token-info: false
      #       3、遠程獲取公鑰 解析token
      jwt:
        key-uri: ${oauth-server}/oauth/token_key

配置ResourceServerConfig

資源服務器只須要添加這一個配置便可

@Configuration
@EnableResourceServer
//Spring Security默認禁用註解 這裏開啓註解
// 結合@PreAuthorize("hasRole('admin')")用來判斷用戶對某個控制層的方法是否有訪問權限
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
//                配置須要權限的url
                .authorizeRequests()
                .anyRequest().authenticated()
                .and().csrf().disable();
        ;
    }

    //如下就是驗證令牌的本地方法 若是使用這種,將上述application.yml的配置註釋掉,同時將oauth2.jks放入resources文件夾
//    @Override
//    public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
//        resources.resourceId("app").tokenStore(tokenStore());
//    }
//
//    @Bean
//    public TokenStore tokenStore() {
//        return new JwtTokenStore(jwtAccessTokenConverter());
//    }
//
//    /**
//     * 非對稱加密算法對token進行簽名
//     *
//     * @return
//     */
//    @Bean
//    public JwtAccessTokenConverter jwtAccessTokenConverter() {
//        final JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
//        // 導入證書
//        KeyStoreKeyFactory keyStoreKeyFactory =
//                new KeyStoreKeyFactory(new ClassPathResource("oauth2.jks"), "mypass".toCharArray());
//        converter.setKeyPair(keyStoreKeyFactory.getKeyPair("oauth2"));
//        return converter;
//    }
}

<font color='red'>注意:</font>

若是使用本地驗證方法,可能會報讀取不到oauth2.jks的錯誤,由於默認不引用resources目錄下的文件,須要在pom.xml中<build>下添加配置

<resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>**/*.*</include>
                </includes>
            </resource>
        </resources>

測試

啓動順序:

  • eureka-server-single
  • oauth-server
  • zuul
  • eureka-client和eureka-ciient1

經過zuul端口訪問eureka-client下的方法 http://localhost:9110/eureka-client/hi

會自動跳到oauth-server的登錄頁面,輸入用戶名和密碼登錄

file

看url,跳轉到了oauth/authorize,這是受權接口,而且後面攜帶了一些zuul配置的信息

file

成功

file

訪問eureka-client1不須要登錄

file

總結

寫的比較簡潔,可是作出來真的花費了兩天的時間精力(仍是太菜了)

沒有什麼文采,原理性的東西也寫不出來,只能記錄一下實踐,你們共同交流

更多文章見我的博客 https://zheyday.github.io/

相關文章
相關標籤/搜索