springsecurity 集成 oauth2

什麼是oAuth2

簡單來說,就是讓一個系統可以直接訪問另一個系統,通過授權碼。

與單點登錄的區別

什麼是單點登錄: 用戶成功登錄A系統,需要訪問B系統時,可以不用輸入用戶名密碼進行認證就可以直接訪問B系統的資源。

什麼是oauth2: A系統徵求用戶的同意後直接訪問B系統,用戶不需要登錄也不需要訪問B系統。

四種授權模式

1)授權碼模式(oauth2 中最安全最完善的一種模式,應用場景最廣泛)
A系統要訪問B系統的資源,A系統詢問用戶是否同意其訪問B系統的資源。如果用戶同意,則B系統生成授權碼給A,A系統帶着授權碼向B系統發送請求,並獲取到令牌 token 和更新令牌 refresh token。(前提:用戶有訪問B系統的權限)

2)簡化模式
跟授權碼模式類似,去掉了授權碼。直接獲得B系統給的 token ,通過 token 訪問B系統

3)密碼模式
用戶直接把自己訪問B系統的賬號密碼告訴 A系統,A系統拿着用戶的密碼去訪問B系統。

4)客戶端模式
A系統直接脫離用戶,以自己的身份去B系統獲取 token,可以說完全是 AB 系統內部的交互,與用戶無關了。該模式不太屬於 oauth2 範疇

OAuth2表結構

oAuth2 自帶有 7 張表

1)獲取表結構地址: https://github.com/spring-projects/spring-security-oauth/blob/master/spring-security-oauth2/src/test/resources/schema.sql

注意:這裏的 sql 默認是 HSQLDB 的,我們用 mysql 的可以把 LONGVARBINARY 數據類型改成 BLOB
oauth_client_details 是核心表,後面測試時只要看這張表即可

表結構字段說明可參考博客 https://blog.csdn.net/qq_34997906/article/details/89609297

在這裏插入圖片描述

創建父工程

本文只貼 配置類代碼,其他具體代碼跟上一篇博客類似,具體可查看文末源碼

注意 spring cloud 的版本匹配,本例用的 springboot2.3,可參考 https://start.spring.io/actuator/info
在這裏插入圖片描述

創建認證模塊

即 B 系統的 oauth2 認證模塊,B系統需要檢測用戶是否登錄,用戶成功登錄了B系統才能授權給A系統去訪問

@Configuration
@EnableWebSecurity
public class SpringsecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private SysUserService userService;

    //配置加密
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder(); //spring security 內置加密算法
    }

    //認證用戶的來源
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(passwordEncoder());
    }

    //Spring Security配置
    public void configure(HttpSecurity hs) throws Exception {
        hs.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginProcessingUrl("/login")
                .permitAll()
                .and()
                .csrf()
                .disable();
    }

    // 對象在oauth2認證服務中要使用,注意方法名不要亂改
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
}
@Configuration
@EnableAuthorizationServer
public class oauthServerConfig extends AuthorizationServerConfigurerAdapter {
    //數據庫對象
    @Autowired
    private DataSource dataSource;

    //認證業務對象
    @Autowired
    private SysUserService userService;

    //授權模式專用對象
    @Autowired
    private AuthenticationManager authenticationManager;

    //客戶端信息來源
    @Bean
    public JdbcClientDetailsService jdbcClientDetailsService() {
        return new JdbcClientDetailsService(dataSource);
    }

    //token保存策略
    @Bean
    public TokenStore tokenStore() {
        return new JdbcTokenStore(dataSource);
    }

    //授權信息保存策略
    @Bean
    public ApprovalStore approvalStore() {
        return new JdbcApprovalStore(dataSource);
    }

    //授權碼模式數據來源
    @Bean
    public AuthorizationCodeServices authorizationCodeServices() {
        return new JdbcAuthorizationCodeServices(dataSource);
    }

    //指定客戶端信息的數據來源
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.withClientDetails(jdbcClientDetailsService());
    }

    //驗證token的策略
    public void configure(AuthorizationServerSecurityConfigurer securityConfigurer) {
        securityConfigurer.allowFormAuthenticationForClients();
        securityConfigurer.checkTokenAccess("isAuthenticated()");
    }

    //oauth2的主配置
    public void configure(AuthorizationServerEndpointsConfigurer endpointsConfigurer) {
        endpointsConfigurer.approvalStore(approvalStore())
                .authenticationManager(authenticationManager)
                .authorizationCodeServices(authorizationCodeServices())
                .tokenStore(tokenStore());
    }

}

創建資源模塊

即 B 系統的資源服務

@Configuration
@EnableResourceServer
public class OauthConfig extends ResourceServerConfigurerAdapter {

    @Autowired
    private DataSource dataSource;

    /**
     * 指定Token的持久化策略
     * InMemoryTokenStore 表示將 token 存儲在內存
     * Redis 表示將 token 存儲在Redis
     * JdbcTokenStore 表示將 token 存儲在數據庫
     * @return
     */
    @Bean
    public TokenStore jdbcTokenStore() {
        return new JdbcTokenStore(dataSource);
    }

    /**
     * 指定當前資源的id和存儲方案
     * @param resource
     * @throws Exception
     */
    public void configure(ResourceServerSecurityConfigurer resource) throws Exception {
        resource.resourceId("source_api").tokenStore(jdbcTokenStore());
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                //指定不同請求方式訪問資源所需的權限
            .antMatchers(HttpMethod.GET, "/**").access("#oauth2.hasScope('read')")
            .antMatchers(HttpMethod.POST, "/**").access("#oauth2.hasScope('write')")
            .antMatchers(HttpMethod.PATCH, "/**").access("#oauth2.hasScope('write')")
            .antMatchers(HttpMethod.PUT, "/**").access("#oauth2.hasScope('write')")
            .antMatchers(HttpMethod.DELETE, "/**").access("#oauth2.hasScope('write')")
                .and()
            .headers().addHeaderWriter((request, response) -> {
            response.addHeader("Access-Control-Allow_Origin", "*");//允許跨域
            //如果是跨域的預檢請求,則原封不動向下傳達請求頭信息
            if(request.getMethod().equals("OPTIONS")) {
                response.setHeader("Access-Control-Allow-Methods", request.getHeader("Access-Control-Allow-Methods"));
                response.setHeader("Access-Control-Allow-Headers", request.getHeader("Access-Control-Allow-Headers"));
            }

        });
    }
}

測試

1)添加測試數據(A系統在B系統註冊的客戶端信息)
B系統需要保存A系統的id,A系統可以訪問哪些資源,都有什麼權限,訪問的模式,回調地址,是否需要用戶同意
在這裏插入圖片描述

2)啓動兩個模塊
注意請求路徑的寫法,是oauth2提供的,我們只需改變參數

  • 首先在網頁上訪問:http://localhost:8081/oauth/authorize?response_type=code&client_id=client01
    去獲取授權碼,這裏需要用戶輸入賬號密碼登錄
    在這裏插入圖片描述

  • 打開 postman 訪問:http://localhost:8081/oauth/token,在 body 中加入如下參數
    grant_type
    client_id
    client_secret
    code
    username
    password
    在這裏插入圖片描述

本項目 GitHub 地址:https://github.com/godXiaogf/springsecurity_oauth2

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章