国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

這篇具有很好參考價(jià)值的文章主要介紹了【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

一.前言

1.principal和credential的區(qū)別

  • principal:能唯一標(biāo)識用戶身份的屬性,一個用戶可以有多個principal

    • 如登錄的唯一標(biāo)識,用戶可以使用用戶名或手機(jī)或郵箱進(jìn)行登錄,這些principal是讓別人知道的
  • credential:憑證,用戶才知道的,簡單的說就是密碼

    • 如:手機(jī)開鎖,可以使用屏幕密碼也可以使用人臉識別,屏幕密碼和人臉是你個人(用戶)才擁有的;

    • principals 和 credentials 組合就是用戶名 / 密碼了。

2.生成私鑰公鑰

  1. 使用命令生成密鑰證書,采用RSA 算法,每個證書包含公鑰和私鑰
    • Keytool 是一個java提供的證書管理工具
      keytool -genkeypair -alias oyjp -keyalg RSA -keypass ouyangjianpeng -keystore ouyangjianpeng.jks -storepass ouyangjianpeng 
      
      -alias:密鑰的別名 
      -keyalg:使用的hash算法 
      -keypass:密鑰的訪問密碼 
      -keystore:密鑰庫文件名,changgou.jks保存了生成的證書 
      -storepass:密鑰庫的訪問密碼 
      
    • 成功后會在當(dāng)前目錄生成一個ouyangjianpeng.jks文件
  2. 查詢證書信息:
    keytool -list -keystore ouyangjianpeng.jks
    
    【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

3.導(dǎo)出公鑰

  • openssl是一個加解密工具包,這里使用openssl來導(dǎo)出公鑰信息。

    • 安裝 openssl:http://slproweb.com/products/Win32OpenSSL.html

      • 安裝資料目錄下的Win64OpenSSL-1_1_1b.exe
    • cmd進(jìn)入ouyangjianpeng.jks文件所在目錄執(zhí)行如下命令:

      keytool -list -rfc --keystore ouyangjianpeng.jks | openssl x509 -inform pem -pubkey
      

      【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

3.用戶認(rèn)證分析

4.認(rèn)證解決方案

4.1.單點(diǎn)登錄

單點(diǎn)登錄(Single Sign On),簡稱為 SSO,是目前比較流行的企業(yè)業(yè)務(wù)整合的解決方案之一。 SSO的定義是在多個應(yīng)用系統(tǒng)中,用戶只需要登錄一次就可以訪問所有相互信任的應(yīng)用系統(tǒng)

  • 分布式系統(tǒng)要實(shí)現(xiàn)單點(diǎn)登錄,通常將認(rèn)證系統(tǒng)獨(dú)立抽取出來,并且將用戶信息存儲在單獨(dú)數(shù)據(jù)庫中,比如 MySQL、Redis,考慮性能要求,通常存儲在Redis中,如下圖:
    【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!
    Java中有很多用戶認(rèn)證的框架都可以實(shí)現(xiàn)單點(diǎn)登錄:

    Apache Shiro. 
    CAS 
    Spring security   
    

4.2.第三方賬號登錄

所謂的第三方登錄,是說基于用戶在第三方平臺上已有的賬號和密碼來實(shí)現(xiàn)應(yīng)用的登錄或者注冊的功能。而第三方平臺一般是已擁有大量用戶的平臺,國外的比如Facebook,Twitter等,國內(nèi)的比如微博、微信、QQ等。
【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

? 第三方認(rèn)證技術(shù)方案最主要是 解決認(rèn)證協(xié)議的通用標(biāo)準(zhǔn)問題,因?yàn)橐獙?shí)現(xiàn)跨系統(tǒng)認(rèn)證,各系統(tǒng)之間要遵循一定的
接口協(xié)議。

  • ? Oauth協(xié)議為用戶資源的授權(quán)提供了一個安全的、開放而又簡易的標(biāo)準(zhǔn)。同時(shí),任何第三方都可以使用Oauth認(rèn)
    證服務(wù),任何服務(wù)提供商都可以實(shí)現(xiàn)自身的OAUTH認(rèn)證服務(wù),因而Oauth是開放的。

  • Oauth協(xié)議目前發(fā)展到2.0版本,1.0版本過于復(fù)雜,2.0版本已得到廣泛應(yīng)用。

使用QQ認(rèn)證的過程:
【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

  1. 用戶訪問網(wǎng)站A,網(wǎng)站A請求QQ授權(quán)服務(wù)器發(fā)送授權(quán)請求給用戶
  2. 用戶確認(rèn)授權(quán)后,返回授權(quán)碼給第三方
  3. 第三方拿到授權(quán)碼后,攜帶授權(quán)碼向QQ授權(quán)服務(wù)器申請令牌
  4. 第三方拿到令牌后,攜帶令牌向QQ請求用戶的基本信息
  5. QQ資源服務(wù)器根據(jù)訪問令牌,返回給第三方用戶的基本信息

4.3.單token系統(tǒng)和雙token系統(tǒng)業(yè)務(wù)邏輯

【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!


【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

二.Spring Security

Spring Security是一個用于快速實(shí)現(xiàn)認(rèn)證/授權(quán)的安全框架。

  • 認(rèn)證(Authentication) :即校驗(yàn)用戶的身份信息是否合法的過程,合法方可繼續(xù)訪問,不合法則拒絕訪問。常見的認(rèn)證方式有:用戶名密碼登錄,二維碼登錄,手機(jī)短信登錄,指紋認(rèn)證等方式。

  • 授權(quán)(Authorization): 即是Authentication認(rèn)證通過后根據(jù)用戶的權(quán)限來控制用戶是否能訪問指定資源,擁有該資源的訪問權(quán)限則正常訪問,沒有權(quán)限則拒絕訪問。

1.快速入門

引入依賴

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

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

編寫controller

@RestController
@RequestMapping("/test")
public class TestController {
    @GetMapping("/hello")
    public String add(){
        return "hello security";
    }
}

訪問頁面時(shí)出現(xiàn)了默認(rèn)的安全認(rèn)證窗口,密碼在控制臺處進(jìn)行顯示。默認(rèn)的用戶名為user
【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

2.基本原理

SpringSecurity本質(zhì)上是一個過濾器鏈。常用過濾器如下

FilterSecurityInterceptor
  • 位于最底端的,是一個方法級權(quán)限過濾器
public class FilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {
    private static final String FILTER_APPLIED = "__spring_security_filterSecurityInterceptor_filterApplied";
    private FilterInvocationSecurityMetadataSource securityMetadataSource;
    private boolean observeOncePerRequest = true;
}
ExceptionTranslationFilter
  • 異常處理過濾器,用來處理在認(rèn)證授權(quán)的過程中拋出的異常信息。
public class ExceptionTranslationFilter extends GenericFilterBean implements MessageSourceAware {
    private void doFilter(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        try {
            chain.doFilter(request, response);
        } catch (IOException var7) {
            throw var7;
        } catch (Exception var8) {
            Throwable[] causeChain = this.throwableAnalyzer.determineCauseChain(var8);
            RuntimeException securityException = (AuthenticationException)this.throwableAnalyzer.getFirstThrowableOfType(AuthenticationException.class, causeChain);
            if (securityException == null) {
                securityException = (AccessDeniedException)this.throwableAnalyzer.getFirstThrowableOfType(AccessDeniedException.class, causeChain);
            }

            if (securityException == null) {
                this.rethrow(var8);
            }

            if (response.isCommitted()) {
                throw new ServletException("Unable to handle the Spring Security Exception because the response is already committed.", var8);
            }

            this.handleSpringSecurityException(request, response, chain, (RuntimeException)securityException);
        }
    }
UsernamePasswordAuthenticationFilter
  • /login的POST請求做攔截,校驗(yàn)表單中用戶名密碼

核心的業(yè)務(wù)邏輯如下

public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        if (this.postOnly && !request.getMethod().equals("POST")) {
            throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());
        } else {
            String username = this.obtainUsername(request);
            username = username != null ? username.trim() : "";
            String password = this.obtainPassword(request);
            password = password != null ? password : "";
            UsernamePasswordAuthenticationToken authRequest = UsernamePasswordAuthenticationToken.unauthenticated(username, password);
            this.setDetails(request, authRequest);
            return this.getAuthenticationManager().authenticate(authRequest);
        }
    }

3.基于數(shù)據(jù)庫中實(shí)現(xiàn)用戶認(rèn)證/授權(quán)

WebSecurityConfigurerAdapter類

  • 引入springSecurity的依賴并做相關(guān)的配置,對資源進(jìn)行保護(hù)。通常需要重寫以下方法:
//可以配置忽略某些請求。
public void configure(WebSecurity web) throws Exception {}

//配置安全攔截機(jī)制控制資源的訪問,可配置匹配哪些請求、哪些可以直接訪問、哪些需要授權(quán)后訪問。 
protected void configure(HttpSecurity http) throws Exception {}

//配置驗(yàn)證的用戶信息源和密碼加密策略,并向容器注入AuthenticationManager對象,這需要在OAuth2中配置(授權(quán)服務(wù)器),配置了AuthenticationManager密碼驗(yàn)證才會生效。 
public void configure(AuthenticationManagerBuilder auth) throws Exception {}

//配置驗(yàn)證管理的Bean 
public AuthenticationManager authenticationManagerBean() throws Exception {}

新增依賴

        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.5.2</version>
        </dependency>
 
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <scope>runtime</scope>
       </dependency>

自定義UserDetail類(偽代碼)

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.blb.java11springsecurity.entity.User;
import com.blb.java11springsecurity.service.IUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
 
import java.util.List;
 
/**
 * 實(shí)現(xiàn)自定義用戶登錄邏輯
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
 
    @Autowired
    private IUserService userService;//用戶表實(shí)現(xiàn)類
 
    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        //按用戶名查詢用戶信息
        User user = userService.getOne(new QueryWrapper<User>().lambda().eq(User::getUsername, s));
        if(user == null){
            throw new UsernameNotFoundException("用戶名不存在");
        }
        //查詢所有用戶權(quán)限 List<String> --> xx,xxx,xxx,xx --> List<Authory>
        List<String> authList = userService.getAuthoritiesByUsername(s);
        String auths = String.join(",", authList);
        //把用戶信息包裝到UserDetails的實(shí)現(xiàn)類User中
        return new org.springframework.security.core.userdetails.User(user.getUsername(),user.getPassword(),
                AuthorityUtils.commaSeparatedStringToAuthorityList(auths));
    }
}

SpringSecurity的核心配置(偽代碼)

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
//啟動Security的驗(yàn)證
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private BCryptPasswordEncoder bCryptPasswordEncoder;
 
    @Autowired
    private UserDetailsService userDetailsService;//引入自定義用戶登錄邏輯
 
    //配置驗(yàn)證用戶的賬號和密碼
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    //使用內(nèi)存中用戶信息進(jìn)行認(rèn)證
		/*auth.inMemoryAuthentication()
                .withUser("zhangsan")
                .password(bCryptPasswordEncoder.encode("123"))
                .roles("ADMIN","USER") //角色
                .and()
                .withUser("lisi")
                .password(bCryptPasswordEncoder.encode("123"))
                .roles("USER"); //權(quán)限
	*/
    //使用自定義UserDetail類定義邏輯進(jìn)行認(rèn)證
        auth.userDetailsService(userDetailsService);
    }
 
    //配置訪問控制
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        //給請求授權(quán)
        http.authorizeRequests()
                //給登錄相關(guān)的請求放行(permitAll即未登陸,定義的路徑依舊不會攔截)
                .antMatchers("/login", "/login.html", "/**/*.css").permitAll()
                //訪問控制(即使登陸了,訪問路徑需要相應(yīng)的權(quán)限)
                .antMatchers("/admin/**").hasAuthority("銷售管理")
                .antMatchers("/user/**").hasAuthority("采購管理")
                //其他路徑進(jìn)行權(quán)限驗(yàn)證,說白了就是攔截
                .anyRequest().authenticated()
                .and()
                //配置自定義登錄
                .formLogin()
                .loginPage("/login.html") //登錄頁面
                .loginProcessingUrl("/login") //處理登錄的url
                .successForwardUrl("/hello.html") //登錄成功后跳轉(zhuǎn)的url
        ;
    }
     
    //提供密碼編碼器,采用加密,加鹽策略。每次加密后結(jié)果都不一樣。賊安全
    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

三.Spring Security集成 OAuth2

  • OAuth2和Spring Security集成,就可以得到一套完整的安全解決方案。然后通過Spring Security OAuth2構(gòu)建一個授權(quán)服務(wù)器來驗(yàn)證用戶身份以提供access_token,并使用這個access_token來從資源服務(wù)器請求數(shù)據(jù)。

1.搭建授權(quán)服務(wù)器

1.0.授權(quán)服務(wù)器簡介

搭建授權(quán)服務(wù)器最重要的是:繼承AuthorizationServerConfigurerAdapter接口并在實(shí)現(xiàn)類上加注解@EnableAuthorizationServer標(biāo)識這是一個授權(quán)服務(wù)器。

  • AuthorizationServerConfigurerAdapter接口有三個方法
    public class AuthorizationServerConfigurerAdapter implements AuthorizationServerConfigurer {
        //配置客戶端信息,即怎么讀取用戶信息 是基于內(nèi)存還是jdbc
    	@Override
    	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    	}
     	 //用來配置令牌(token)的訪問端點(diǎn)和令牌服務(wù)(token services)。
    	@Override
    	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    	}
     	//用來配置令牌端點(diǎn)(Token Endpoint)的安全約束。
    	@Override
    	public void configure(AuthorizationServerSecurityConfigurer security) throws Exception{
    	}
    }
    

ClientDetailsServiceConfigurer:配置客戶端信息

  • 可以使用內(nèi)存或JDBC來實(shí)現(xiàn)客戶端詳情服務(wù), ClientDetails有如下幾個重要屬性:
        clients.inMemory()
                //客戶端id
                .withClient("client_1")
                //客戶端secret
                .secret(passwordEncoder().encode("123456"))
                //回調(diào)地址
                .redirectUris("https://www.baidu.com/")
                /* OAuth2為我們提供了四種授權(quán)方式:
                 * 1、授權(quán)碼模式(authorization code)用在客戶端與服務(wù)端應(yīng)用之間授權(quán)
                 * 2、簡化模式(implicit)用在移動app或者web app(這些app是在用戶的設(shè)備上的,如在手機(jī)上調(diào)起微信來進(jìn)行認(rèn)證授權(quán))
                 * 3、密碼模式(resource owner password credentials)應(yīng)用直接都是受信任的(都是由一家公司開發(fā)的)
                 * 4、客戶端模式(client credentials)用在應(yīng)用API訪問
                 */
                .authorizedGrantTypes("password", "client_credentials", "refresh_token", "authorization_code")
                //授權(quán)范圍,默認(rèn)為空,表示客戶端擁有全部的訪問范圍。
                .scopes("all")
                //accessToken有效期
                .accessTokenValiditySeconds(accessTokenValiditySeconds)
                //refreshToken有效期
                .refreshTokenValiditySeconds(refreshTokenValiditySeconds);

AuthorizationServerEndpointsConfigurer:配置令牌訪問端點(diǎn)

  • 使用@EnableAuthorizationServer注解后,應(yīng)用啟動后將自動生成幾個Endpoint:

    /oauth/authorize:驗(yàn)證
    /oauth/token:獲取token
    /oauth/confirm_access:用戶授權(quán)
    /oauth/error:認(rèn)證失敗
    /oauth/check_token:資源服務(wù)器用來校驗(yàn)token
    /oauth/token_key:如果使用JWT令牌,則公開用于令牌驗(yàn)證的公鑰
    

AuthorizationServerSecurityConfigurer:用來配置令牌端點(diǎn)(Token Endpoint)的安全約束

	上面的/oauth/check_token和/oauth/token_key端點(diǎn),他們都是用于檢查令牌的,默認(rèn)受保護(hù)denyAll()。
	使用tokenKeyAccess()checkTokenAccess()方法會打開這些端點(diǎn)以供使用,如:
        // 允許check_token訪問
        oauthServer.checkTokenAccess("permitAll()");
        // 允許表單認(rèn)證
        oauthServer.allowFormAuthenticationForClients();

Token存儲方式

OAuth2存儲token值的方式由多種,所有的實(shí)現(xiàn)方式都是實(shí)現(xiàn)了TokenStore接口
	InMemoryTokenStore:  存儲在本機(jī)內(nèi)存
	JdbcTokenStore: 存儲在數(shù)據(jù)庫
	JwtTokenStore:  不會存儲到任何介質(zhì)中
	RedisTokenStore: 存儲在Redis

用戶(客戶端)信息存儲方式

內(nèi)存中
數(shù)據(jù)庫中

客戶端信息存儲到 oauth_client_details 表中,建表語句可以從如下網(wǎng)站找到:
spring-security-oauth/schema.sql at main · spring-attic/spring-security-oauth · GitHub

oauth_client_details :客戶端賬號密碼、授權(quán)、回調(diào)地址等重要信息;核心表。
oauth_access_token :存儲access_token。
oauth_refresh_token :存儲refresh_token。
oauth_client_token :存儲從服務(wù)端獲取的token數(shù)據(jù)。
oauth_code :存儲授權(quán)碼。
oauth_approvals :存儲授權(quán)成功的客戶端信息。

1.1.引入依賴

<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>
    <version>2.3.4.RELEASE</version>
</dependency>

或者 引入spring cloud oauth2依賴

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
 
<!-- spring cloud -->
<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-dependencies</artifactId>
            <version>Hoxton.SR8</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
    </dependencies>
</dependencyManagement>

完整如下:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
        <relativePath/>
    </parent>
   
    <groupId>com.oyjp</groupId>
    <artifactId>spring-boot-oauth2-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
    </properties>

    <!-- spring cloud -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR8</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <dependencies>
        <!-- SpringBoot整合Web組件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>

        <!-- springboot整合freemarker -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

1.2.application.yaml

server:
  port: 8080

spring:
  application:
    name: oauth2-center-server

logging:
  level:
    root: info
    org.springframework.security: DEBUG

1.3.Oauth2授權(quán)服務(wù)配置

具體實(shí)現(xiàn)

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

//配置授權(quán)中心信息
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    /**
     * accessToken有效期 兩小時(shí)
     */
    private int accessTokenValiditySeconds = 7200;
 
    /**
     * refreshToken有效期 兩小時(shí)
     */
    private int refreshTokenValiditySeconds = 7200;
 
    /**
     * 添加商戶信息
     * @param clients 客戶端即可
     * @throws Exception 異常
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
           		//配置client_id
                .withClient("client_1")
                //配置client-secret
                .secret(passwordEncoder().encode("123456"))
                //配置redirect_uri,用于授權(quán)成功后跳轉(zhuǎn)
                .redirectUris("https://www.baidu.com/")
                 //配置grant_type,表示授權(quán)類型
                /* OAuth2為我們提供了四種授權(quán)方式:
                 * 1、授權(quán)碼模式(authorization code)用在客戶端與服務(wù)端應(yīng)用之間授權(quán)
                 * 2、簡化模式(implicit)用在移動app或者web app(這些app是在用戶的設(shè)備上的,如在手機(jī)上調(diào)起微信來進(jìn)行認(rèn)證授權(quán))
                 * 3、密碼模式(resource owner password credentials)應(yīng)用直接都是受信任的(都是由一家公司開發(fā)的)
                 * 4、客戶端模式(client credentials)用在應(yīng)用API訪問
                 */
  				.authorizedGrantTypes("password", "client_credentials", "refresh_token", "authorization_code", "implicit")
                //授權(quán)范圍
                .scopes("all")
                //配置訪問token的有效期
                .accessTokenValiditySeconds(accessTokenValiditySeconds)
                //配置刷新token的有效期
                .refreshTokenValiditySeconds(refreshTokenValiditySeconds);
    }

    /**
     * 設(shè)置token類型
     * @param endpoints
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.authenticationManager(authenticationManager())
                .allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST); //支持GET,POST請求
        endpoints.userDetailsService(userDetailsService());
    }
 
    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
        // 允許表單認(rèn)證
        oauthServer.allowFormAuthenticationForClients();
        // 允許check_token訪問
        oauthServer.checkTokenAccess("permitAll()");
    }
 
    @Bean
    AuthenticationManager authenticationManager() {
        AuthenticationManager authenticationManager = new AuthenticationManager() {
            @Override
            public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                return daoAuhthenticationProvider().authenticate(authentication);
            }

        };
        return authenticationManager;
    }
 
    @Bean
    public AuthenticationProvider daoAuhthenticationProvider() {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(userDetailsService());
        daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        return daoAuthenticationProvider;
    }
 
    /**
     * 設(shè)置添加用戶信息,正常應(yīng)該從數(shù)據(jù)庫中讀取
     * @return UserDetailsService
     */
    @Bean
    UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
        userDetailsService.createUser(User.withUsername("user_1").password(passwordEncoder().encode("123456"))
                .authorities("ROLE_USER").build());
        userDetailsService.createUser(User.withUsername("user_2").password(passwordEncoder().encode("1234567"))
                .authorities("ROLE_USER").build());
        return userDetailsService;
    }
 
    /**
     * 采用BCryptPasswordEncoder對密碼進(jìn)行編碼
     * @return PasswordEncoder
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

1.4.SpringSecurity配置

import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Component;
/**
 *  添加Security權(quán)限配置
 */
@Component
public class SecurityConfig  extends WebSecurityConfigurerAdapter {
     /***
     * 忽略安全攔截的URL
     * @param web
     * @throws Exception
     */
    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/oauth/**","/login.html","/css/**","/data/**","/fonts/**","/img/**","/js/**");
    }

    /**
     *  授權(quán)中心管理器
     * @return AuthenticationManager
     * @throws Exception 異常
     */
    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }
 
    //@Bean
    //public PasswordEncoder passwordEncoder() {
    //    return new BCryptPasswordEncoder();
    //}
 
    /**
     *  攔截所有請求,使用httpBasic方式登陸
     * @param http 請求
     * @throws Exception 異常
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/**").fullyAuthenticated().and().httpBasic();
    }

}

1.5.啟動類

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

1.測試授權(quán)碼模式

  1. 請求 http://localhost:8080/oauth/authorize?response_type=code&client_id=client_1&redirect_uri=https://www.baidu.com/

    • 授權(quán)服務(wù)器將攜帶授權(quán)碼code然后轉(zhuǎn)發(fā)至redirect_uri=https://www.baidu.com/然
      【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!
  2. 使用授權(quán)碼獲取accessToken
    POST請求 http://localhost:8080/oauth/token?grant_type=authorization_code&client_id=client_1&client_secret=123456&code=EwaTib&redirect_uri=https://www.baidu.com/&scope=all
    【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

2.測試密碼模式

POST請求 http://localhost:8080/oauth/token?grant_type=password&client_id=client_1&client_secret=123456&code=YerSeW&scope=all&username=user_1&password=123456
【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

2.搭建資源服務(wù)器

1.0.前言

搭建資源服務(wù)器最重要的是:繼承ResourceServerConfigurerAdapter接口并在實(shí)現(xiàn)類上加注解@EnableResourceServer標(biāo)識這是一個資源服務(wù)器。

  • 該接口只有兩個方法

    public class ResourceServerConfigurerAdapter implements ResourceServerConfigurer {
     	//配置哪些可以訪問,哪些不可訪問,默認(rèn)情況下所有不在/oauth/**下的資源都是受保護(hù)的資源
    	@Override
    	public void configure(HttpSecurity http) throws Exception {
    		http.authorizeRequests().anyRequest().authenticated();
    	}
    	
    	//它可以為資源服務(wù)器添加一個特定的屬性,如resourceId,也就是說我們一個授權(quán)服務(wù)器可能對應(yīng)多個資源服務(wù)器,
    	//可以為每個資源服務(wù)器添加一個resourceId屬性進(jìn)行區(qū)分,可選,但建議使用,如果存在,auth服務(wù)器將進(jìn)行驗(yàn)證。
    	@Override
    	public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
    	}
    }
    

1.1.引入依賴

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.3.2.RELEASE</version>
        <relativePath/>
    </parent>
   
    <groupId>com.oyjp</groupId>
    <artifactId>spring-boot-oauth2-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Hoxton.RELEASE</spring-cloud.version>
    </properties>

    <!-- spring cloud -->
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>Hoxton.SR8</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>


    <dependencies>
        <!-- SpringBoot整合Web組件 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

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

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-oauth2</artifactId>
        </dependency>

        <!-- springboot整合freemarker -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-freemarker</artifactId>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

1.2.application.yaml

server:
  port: 8081


spring:
  application:
    name: oauth2-resource-server

security:
  oauth2:
    resource:
      ####從認(rèn)證授權(quán)中心上驗(yàn)證token
      tokenInfoUri: http://localhost:8080/oauth/check_token
      preferTokenInfo: true
    client:
      accessTokenUri: http://localhost:8080/oauth/token
      userAuthorizationUri: http://localhost:8080/oauth/authorize
      ###appid
      clientId: client_1
      ###appSecret
      clientSecret: 123456

logging:
  level:
    root: info
    org.springframework.security: DEBUG

1.3.oauth2資源服務(wù)配置

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;

/**
 * @Description: 資源攔截配置
 */
@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        // 對 api/order 請求進(jìn)行攔截
        http.authorizeRequests().antMatchers("/api/test/**").authenticated();
    }
}

1.4.請求測試類


@RestController
@RequestMapping("/api/test")
public class TestController {
    @RequestMapping("/add")
    public String addOrder() {
        return "add success!";
    }
}

1.5.啟動類開啟Oauth2

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
@SpringBootApplication
@EnableOAuth2Sso
public class Oauth2ResourceServerApplication {
    public static void main(String[] args) {
        SpringApplication.run(Oauth2ResourceServerApplication.class, args);
    }

}

1.5.1.授權(quán)服務(wù)器和資源服務(wù)聯(lián)合測試

  1. 沒授權(quán)時(shí)請求http://127.0.0.1:8081/api/test/add
    【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!
  2. 授權(quán)時(shí)請求http://127.0.0.1:8081/api/test/add
  • 先獲取token(密碼模式)

    • http://localhost:8080/oauth/token?grant_type=password&client_id=client_1&client_secret=123456&code=YerSeW&scope=all&username=user_1&password=123456
      【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!
  • 使用token訪問資源服務(wù)器
    【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

3.授權(quán)服務(wù)器改成動態(tài)數(shù)據(jù)庫查詢的方式

1.1.下載oauth2官方建表語句

spring-security-oauth/schema.sql at main · spring-attic/spring-security-oauth · GitHub
【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

我用的是Mysql,對于上面鏈接里的建表語句,有某些字段為`LONGVARBINARY`類型,它對應(yīng)mysql的`blob`類型,這需要改下,
另外主鍵是varchar(255),如果又用的utf8mb4編碼,主鍵長度會超限制,所以這個主鍵長度最好也要改一下。

oauth_client_details :客戶端賬號密碼、授權(quán)、回調(diào)地址等重要信息;核心表。
oauth_access_token :存儲access_token。
oauth_refresh_token :存儲refresh_token。
oauth_client_token :存儲從服務(wù)端獲取的token數(shù)據(jù)。
oauth_code :存儲授權(quán)碼。
oauth_approvals :存儲授權(quán)成功的客戶端信息

【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

1.2.新增依賴

       <!-- mysql -->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
 
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jdbc</artifactId>
        </dependency>

1.3./修改授權(quán)服務(wù)器

1.修改配置文件

server:
  port: 8080


spring:
  application:
    name: oauth2-center-server
    
  datasource:
    hikari:
      connection-test-query: SELECT 1
      minimum-idle: 1
      maximum-pool-size: 5
      pool-name: dbcp1
    driver-class-name: com.mysql.cj.jdbc.Driver
    url: jdbc:mysql://localhost:3306/oauth2_test?autoReconnect=true&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password: root


logging:
  level:
    root: info
    org.springframework.security: DEBUG

2.修改AuthorizationServerConfig

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JdbcTokenStore;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;
import javax.sql.DataSource;

/**
 * @Description: 配置授權(quán)中心信息
 */
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
 
    //數(shù)據(jù)源,用于從數(shù)據(jù)庫獲取數(shù)據(jù)進(jìn)行認(rèn)證操作,測試可以從內(nèi)存中獲取
    @Autowired
    @Qualifier("dataSource")
    private DataSource dataSource;
 
 
    /**
     * accessToken有效期 兩小時(shí)
     */
    private int accessTokenValiditySeconds = 7200;
 
    /**
     * refreshToken有效期 兩小時(shí)
     */
    private int refreshTokenValiditySeconds = 7200;
 
    @Bean
    public TokenStore tokenStore() {
        // return new InMemoryTokenStore(); //使用內(nèi)存中的 token store
        return new JdbcTokenStore(dataSource); /// 使用Jdbctoken store
    }
 
 
    /**
     * 添加商戶信息
     *
     * @param clients 商戶
     * @throws Exception 異常
     */
    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.jdbc(dataSource)
                //測試首次運(yùn)行可以指定測試數(shù)據(jù),如果數(shù)據(jù)庫中沒有則不報(bào)錯,如果有或者第二次運(yùn)行會報(bào)錯,因?yàn)閿?shù)據(jù)庫已經(jīng)存在了,需要注釋掉
                .withClient("client_1")
                //商戶secret
                .secret(passwordEncoder().encode("123456"))
                //回調(diào)地址
                .redirectUris("https://www.baidu.com/")
                /* OAuth2為我們提供了四種授權(quán)方式:
                 * 1、授權(quán)碼模式(authorization code)用在客戶端與服務(wù)端應(yīng)用之間授權(quán)
                 * 2、簡化模式(implicit)用在移動app或者web app(這些app是在用戶的設(shè)備上的,如在手機(jī)上調(diào)起微信來進(jìn)行認(rèn)證授權(quán))
                 * 3、密碼模式(resource owner password credentials)應(yīng)用直接都是受信任的(都是由一家公司開發(fā)的)
                 * 4、客戶端模式(client credentials)用在應(yīng)用API訪問
                 */
  				.authorizedGrantTypes("password", "client_credentials", "refresh_token", "authorization_code", "implicit")
                //授權(quán)范圍
                .scopes("all")
                //accessToken有效期
                .accessTokenValiditySeconds(accessTokenValiditySeconds)
                //refreshToken有效期
                .refreshTokenValiditySeconds(refreshTokenValiditySeconds);
    }
 
    /**
     * 設(shè)置token類型
     * @param endpoints
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.authenticationManager(authenticationManager())
                .allowedTokenEndpointRequestMethods(HttpMethod.GET,HttpMethod.POST);
        endpoints.userDetailsService(userDetailsService());
    }
 
    @Override
    public void configure(AuthorizationServerSecurityConfigurer oauthServer) {
        // 允許表單認(rèn)證
        oauthServer.allowFormAuthenticationForClients();
        // 允許check_token訪問
        oauthServer.checkTokenAccess("permitAll()");
    }
 
    @Bean
    AuthenticationManager authenticationManager() {
        AuthenticationManager authenticationManager = new AuthenticationManager() {
            @Override
            public Authentication authenticate(Authentication authentication) throws AuthenticationException {
                return daoAuhthenticationProvider().authenticate(authentication);
            }
 
        };
        return authenticationManager;
    }
 
    @Bean
    public AuthenticationProvider daoAuhthenticationProvider() {
        DaoAuthenticationProvider daoAuthenticationProvider = new DaoAuthenticationProvider();
        daoAuthenticationProvider.setUserDetailsService(userDetailsService());
        daoAuthenticationProvider.setHideUserNotFoundExceptions(false);
        daoAuthenticationProvider.setPasswordEncoder(passwordEncoder());
        return daoAuthenticationProvider;
    }
 
    /**
     * 設(shè)置添加用戶信息,正常應(yīng)該從數(shù)據(jù)庫中讀取
     *
     * @return UserDetailsService
     */
    @Bean
    UserDetailsService userDetailsService() {
        InMemoryUserDetailsManager userDetailsService = new InMemoryUserDetailsManager();
        userDetailsService.createUser(User.withUsername("user_1").password(passwordEncoder().encode("123456"))
                .authorities("ROLE_USER").build());
        userDetailsService.createUser(User.withUsername("user_2").password(passwordEncoder().encode("1234567"))
                .authorities("ROLE_USER").build());
        return userDetailsService;
    }
 
    /**
     * 設(shè)置加密方式
     *
     * @return PasswordEncoder
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

4.測試

【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

檢查數(shù)據(jù)庫發(fā)現(xiàn)測試商戶已經(jīng)導(dǎo)入到數(shù)據(jù)庫了
【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!
【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!
【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

四.4種授權(quán)模式

OAuth2為我們提供了四種授權(quán)方式:

  1. 授權(quán)碼模式(authorization_code)用在客戶端與服務(wù)端應(yīng)用之間授權(quán)
  2. 簡化模式(implicit)用在移動app或者web app(這些app是在用戶的設(shè)備上的,如:在手機(jī)上調(diào)起微信來進(jìn)行認(rèn)證授權(quán))
  3. 密碼模式(password)應(yīng)用直接都是受信任的(都是由一家公司開發(fā)的)
  4. 客戶端模式(client_credentials)用在應(yīng)用API訪問

1.授權(quán)碼模式

  1. 客戶端請求第三方授權(quán),將重定向到授權(quán)服務(wù)器,重定向時(shí)會附加客戶端信息,然后客戶端要求用戶給予授權(quán),如:

    • http://localhost:8080/oauth/authorize?response_type=code&client_id=client_1&redirect_uri=https://www.baidu.com/

      • 參數(shù)列表如下:

        client_id:客戶端標(biāo)識。
        response_code:授權(quán)碼模式固定為code。
        scope:客戶端權(quán)限范圍。
        redirect_uri:跳轉(zhuǎn)uri,當(dāng)授權(quán)碼申請成功后會跳轉(zhuǎn)到此地址,并在后邊帶上code參數(shù)。
        
  2. 瀏覽器出現(xiàn)向授權(quán)服務(wù)器授權(quán)頁面,用戶同意給客戶端授權(quán)。

  3. 授權(quán)服務(wù)器將授權(quán)碼發(fā)送給客戶端通過redirect_uri攜帶code

  4. 客戶端拿著授權(quán)碼想授權(quán)服務(wù)器申請token

    • http://localhost:8080/oauth/token?grant_type=authorization_code&client_id=client_1&client_secret=123456&code=iZ81fR&redirect_uri=https://www.baidu.com/&scope=all

    • 參數(shù)列表如下:

      client_id:客戶端標(biāo)識。
      client_secret:客戶端密鑰。
      grant_type:授權(quán)類型,填寫authorization_code。
      code:授權(quán)碼,授權(quán)碼只使用一次就失效。
      redirect_uri:申請授權(quán)碼時(shí)的跳轉(zhuǎn)url。
      
  5. 授權(quán)服務(wù)器返回令牌(access_token

  6. 客戶端請求資源服務(wù)器的資源,資源服務(wù)校驗(yàn)令牌合法性,完成授權(quán)

  7. 資源服務(wù)器返回受保護(hù)資源

總結(jié):

  • 這種模式是四種模式中最安全的,一般用于client是Web服務(wù)器端應(yīng)用或第三方App調(diào)用資源服務(wù)的時(shí)候,因?yàn)樵谶@種模式中access_token不經(jīng)過瀏覽器或者移動端的App,而是直接從服務(wù)端去交換,這樣就最大限度的減少了令牌泄露的風(fēng)險(xiǎn)。

測試

  1. 請求認(rèn)證服務(wù)獲取授權(quán)碼

    • http://localhost:8080/oauth/authorize?response_type=code&client_id=client_1&redirect_uri=https://www.baidu.com/
  2. 跳轉(zhuǎn)到登錄頁面: 輸入賬號:user_1 密碼:123456,登錄進(jìn)入授權(quán)頁面:
    【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

  3. 進(jìn)入授權(quán)頁面
    【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

  4. 點(diǎn)擊Authorize,確認(rèn)授權(quán)后, 認(rèn)證服務(wù)攜帶授權(quán)碼跳轉(zhuǎn)redirect_uri,code=pfiYeD就是返回的授權(quán)碼, 每一個授權(quán)碼只能使用一次
    https://www.baidu.com/?code=pfiYeD
    【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

  5. 使用該code申請令牌
    http://localhost:8080/oauth/token?grant_type=authorization_code&client_id=client_1&client_secret=123456&code=pfiYeD&redirect_uri=https://www.baidu.com/&scope=all
    【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

可能你會遇到返回沒有refresh_token的情況,檢查看下客戶端配置authorizedGrantTypes是否支持refresh_token,我上面配置了才會返回,如下:

.authorizedGrantTypes("authorization_code", "client_credentials", "password", "implicit", "refresh_token")

2.密碼模式

步驟一

  • 資源擁有者將用戶名、密碼發(fā)送給客戶端。

步驟二

  • 客戶端拿著資源擁有者的用戶名、密碼向授權(quán)服務(wù)器請求令牌,如下:

  • http://localhost:8080/oauth/token?grant_type=password&client_id=client_1&client_secret=123456&code=YerSeW&scope=all&username=user_1&password=123456

    • 參數(shù)列表如下:
      client_id:客戶端標(biāo)識。
      client_secret:客戶端密鑰。
      grant_type:授權(quán)類型,填寫password。
      username:資源擁有者用戶名。
      password:資源擁有者密碼。
      

步驟三

  • 授權(quán)服務(wù)器將令牌發(fā)送給client。

總結(jié)

  • 這種模式十分簡單,但直接將用戶敏感信息泄露給了client,因此這就說明這種模式只能用于client是我們自己開發(fā)的情況下。

測試請求令牌,如下:
【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

2.1.密碼模式與授權(quán)碼模式區(qū)別

  • 授權(quán)碼模式申請授權(quán)碼的過程是用戶直接與認(rèn)證服務(wù)器進(jìn)行交互,然后授權(quán)結(jié)果由認(rèn)證服務(wù)器告知第三方客戶端,也就是不會向第三方客戶端暴露服務(wù)提供商的用戶密碼信息。

  • 密碼模式,是用戶將用戶密碼信息交給第三方,然后由第三方向服務(wù)提供商進(jìn)行認(rèn)證和資源請求。

    • 絕大多數(shù)的服務(wù)提供商都會選擇使用授權(quán)碼模式,避免自己的用戶密碼暴漏給第三方。所以密碼模式只適用于服務(wù)提供商對第三方廠商高度信任的情況下才能使用。
  • 客戶端模式、簡化模式的應(yīng)用很少

3.簡化模式

步驟一

  • 資源擁有者打開客戶端,客戶端要求資源擁有者給預(yù)授權(quán),它將瀏覽器重定向到授權(quán)服務(wù)器,重定向時(shí)會附加客戶端的身份信息,如:

    • http://localhost:8080/oauth/authorize?client_id=client_1&response_type=token&scope=all&redirect_uri=https://www.baidu.com/
      • 參數(shù)同授權(quán)碼模式,將response_type改為token即可。

步驟二

  • 瀏覽器出現(xiàn)向授權(quán)服務(wù)器授權(quán)頁面,之后用戶同意授權(quán)。

步驟三

  • 授權(quán)服務(wù)器將授權(quán)碼和令牌到重定向uri之后。

測試

  • 瀏覽器訪問認(rèn)證頁面:

    • http://localhost:8080/oauth/authorize?client_id=client_1&response_type=token&scope=all&redirect_uri=https://www.baidu.com/

【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

  • 輸入賬號:user_1 密碼:123456,登錄進(jìn)入授權(quán)頁面:

【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

  • 確認(rèn)授權(quán)后,瀏覽器會重定向到指定的redirect_uri路徑,并將token存放在uri路徑之后。

【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

  • https://www.baidu.com/#access_token=c2535eca-d9b5-4176-830b-aea1fa2ccf4c&token_type=bearer&expires_in=7199

4.客戶端模式

步驟一

  • 客戶端向授權(quán)服務(wù)器發(fā)送自己的身份信息,并請求令牌。

步驟二

  • 確認(rèn)客戶端身份無誤后,將令牌發(fā)送給client,請求如下:

    • http://localhost:8080/oauth/token?client_id=client_1&client_secret=123456&grant_type=client_credentials&scopes=all

    • 參數(shù)列表如下:

      client_id:客戶端標(biāo)識。
      client_secret:客戶端密鑰。
      grant_type:授權(quán)類型,填寫client_credentials。
      

總結(jié):

  • 這種模式是最方便但最不安全的模式。因此這就要求我們對client完全信任,而client本身也是安全的,因此這種模式一般用來提供給我們完全信任的服務(wù)端使用。

測試請求令牌,如下:

【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

五.Spring Security OAuth2集成JWT

1.生成JTW

  1. 修改tokenStor為JwtTokenStore
    //    //令牌持久化存儲接口
    @Bean
    public TokenStore tokenStore() {
        // return new InMemoryTokenStore(); //使用內(nèi)存中的 token store
        // return new JdbcTokenStore(dataSource); /// 使用Jdbctoken store
        return new JwtTokenStore(accessTokenConverter());

    }
    //jwt令牌轉(zhuǎn)換器
    @Bean
    public JwtAccessTokenConverter accessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("abc123");
        return converter;
    }
  1. 設(shè)置AuthorizationServerEndpointsConfigurer的tokenStore、tokenEnhancer
   //端點(diǎn)設(shè)置自定義token存儲,token增強(qiáng)
   endpoints.tokenStore(tokenStore()).tokenEnhancer(accessTokenConverter());
  1. 使用密碼模式訪問
  • http://localhost:8080/oauth/token?grant_type=password&client_id=client_1&client_secret=123456&code=YerSeW&scope=all&username=user_1&password=123456
    • 解析access_token

【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!

2、自定義Payload

將自定義的TokenEnhancer加入到TokenEnhancerChain中,最后設(shè)置到端點(diǎn)中endpoints.tokenEnhancer(tokenEnhancerChain) 。

  1. 授權(quán)服務(wù)器新增TokenEnhancer實(shí)現(xiàn)類

    import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
    import org.springframework.security.oauth2.common.OAuth2AccessToken;
    import org.springframework.security.oauth2.provider.OAuth2Authentication;
    import org.springframework.security.oauth2.provider.token.TokenEnhancer;
    import org.springframework.stereotype.Component;
    import java.util.HashMap;
    import java.util.Map;
    
    @Component
    public class CustomTokenEnhancer implements TokenEnhancer {
        @Override
        public OAuth2AccessToken enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication) {
            Map<String, Object> additionalInfo = new HashMap<>(16);
            additionalInfo.put("userid", "123");
            ((DefaultOAuth2AccessToken) accessToken).setAdditionalInformation(additionalInfo);
            return accessToken;
        }
    }
    
  2. 將tokenEnhancer注入,追加到TokenEnhancerChain中,并設(shè)置到endponits

    /**
     * 設(shè)置token類型
     *
     * @param endpoints
     */
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
        endpoints.authenticationManager(authenticationManager()).allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST);
        //用戶信息
        endpoints.userDetailsService(userDetailsService());
        //自定義token存儲,token增強(qiáng)
        //endpoints.tokenStore(tokenStore()).tokenEnhancer(accessTokenConverter());

        TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();
        tokenEnhancerChain.setTokenEnhancers(Arrays.asList(tokenEnhancer, accessTokenConverter()));
        endpoints.tokenEnhancer(tokenEnhancerChain);
        endpoints.tokenEnhancer(tokenEnhancer);
    }
  1. 使用密碼模式訪問
  • http://localhost:8080/oauth/token?grant_type=password&client_id=client_1&client_secret=123456&code=YerSeW&scope=all&username=user_1&password=123456

【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!文章來源地址http://www.zghlxwxcb.cn/news/detail-424017.html

到了這里,關(guān)于【SpringBoot】自從集成spring-security-oauth2后,實(shí)現(xiàn)統(tǒng)一認(rèn)證授權(quán)so easy!的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • Spring Security Oauth2.1 最新版 1.1.0 整合 (基于 springboot 3.1.0)gateway 完成授權(quán)認(rèn)證

    Spring Security Oauth2.1 最新版 1.1.0 整合 (基于 springboot 3.1.0)gateway 完成授權(quán)認(rèn)證

    目錄 背景 demo地址 版本 Spring Boot 3.1 Spring Authorization Server 1.1.0 基礎(chǔ) spring security OAuth2 模塊構(gòu)成 授權(quán)方式 認(rèn)證方式 集成過程 官方demo 代碼集成 依賴 授權(quán)服務(wù)AuthorizationServerConfig配置 重要組件 測試 查看授權(quán)服務(wù)配置 訪問授權(quán)服務(wù) 授權(quán) 回調(diào) 獲取?access_token 獲取用戶信息 個性

    2024年02月11日
    瀏覽(24)
  • SpringBoot2.3集成Spring Security(二) JWT認(rèn)證

    SpringBoot2.3集成Spring Security(二) JWT認(rèn)證

    緊接上文,我們已經(jīng)完成了 SpringBoot中集成Spring Security,并且用戶名帳號和密碼都是從數(shù)據(jù)庫中獲取。但是這種方式還是不能滿足現(xiàn)在的開發(fā)需求。 使用JWT的好處: 無狀態(tài)認(rèn)證:JWT本身包含了認(rèn)證信息和聲明,服務(wù)器不需要在會話中保存任何狀態(tài)。這樣使得應(yīng)用程序可以更加

    2024年02月11日
    瀏覽(22)
  • Spring Security OAuth2.0(5):Spring Security工作原理

    Spring Security OAuth2.0(5):Spring Security工作原理

    qquad Spring Security 所解決的問題就是安全訪問控制,而安全訪問控制功能其實(shí)就是所有進(jìn)入系統(tǒng)的請求進(jìn)行攔截,校驗(yàn)每個請求是否能夠訪問它所期望的資源。Spring Security 對Web資源的保護(hù)是通過Filter入手的,所以從這個Filter入手,逐步深入Spring Security原理。 $qquad%當(dāng)初始化

    2024年02月17日
    瀏覽(22)
  • Spring Security OAuth2.0(3):Spring Security簡單入門

    Spring Security OAuth2.0(3):Spring Security簡單入門

    Spring Security 快速入門。 本章代碼已分享至Gitee:https://gitee.com/lengcz/security-spring-security qquad Spring Secutiry 是一個能夠?yàn)榛赟pring的企業(yè)應(yīng)用系統(tǒng)提供聲明式的安全訪問控制解決方案的安全框架。由于它是Spring生態(tài)系統(tǒng)的一員,因此它伴隨著整個Spring生態(tài)系統(tǒng)不斷修正、升級,

    2024年02月13日
    瀏覽(28)
  • Spring Security OAuth 2.0

    Spring Security OAuth 2.0

    1 概念 OAuth 2.0 到底是什么呢?我們先從字面上來分析下。OAuth 2.0 一詞中的字母 “O” 是 Open 的簡稱,表示 “開放” , “Auth” 表示 “授權(quán)”,連在一起就表示 “開放授權(quán)”。 OAuth 2.0是一種授權(quán)框架,提供了一套規(guī)范和協(xié)議,用于實(shí)現(xiàn)授權(quán)流程和訪問令牌的管理,而非單個

    2024年02月16日
    瀏覽(22)
  • Spring Security OAuth2詳解

    Spring Security OAuth2詳解

    spring security oauth2框架即spring security + OAuth2,spring security上一篇文章已經(jīng)講過,接下來講講OAuth2,它是行業(yè)標(biāo)準(zhǔn)的授權(quán)協(xié)議,旨在為開發(fā)人員提供簡單易用的授權(quán)流程;OAuth 定義了四種角色: 資源所有者:能夠授予對受保護(hù)資源的訪問權(quán)限的實(shí)體,當(dāng)資源所有者是一個人時(shí),

    2024年02月03日
    瀏覽(27)
  • Spring Security OAuth2.0 - 學(xué)習(xí)筆記

    Spring Security OAuth2.0 - 學(xué)習(xí)筆記

    OAuth2.0是一個開放標(biāo)準(zhǔn),允許用戶授權(quán)第三方應(yīng)用程序訪問他們存儲在另外的服務(wù)提供者上的信息,而不需要將用戶和密碼提供給第三方應(yīng)用或分享數(shù)據(jù)的所有內(nèi)容。 1)授權(quán)碼模式 2)簡化模式 3)密碼模式 4)客戶端模式 普通令牌只是一個隨機(jī)的字符串,沒有特殊的意義,

    2024年02月16日
    瀏覽(59)
  • Spring Security實(shí)現(xiàn)OAuth2協(xié)議及實(shí)戰(zhàn)

    Spring Security實(shí)現(xiàn)OAuth2協(xié)議及實(shí)戰(zhàn)

    文章篇幅較長,愿讀者耐心看完。如有不足之處,請指正。 一.OAuth2介紹 1.1 OAuth2是什么 怎么用 OAuth2是目前最流行的授權(quán)協(xié)議,用來授權(quán)第三方應(yīng)用,獲取用戶數(shù)據(jù)。 舉個例子:快遞員想要進(jìn)入小區(qū),有3種方式。1是業(yè)主遠(yuǎn)程開門,2是業(yè)主告訴門禁密碼,3是使用令牌(Oaut

    2024年02月08日
    瀏覽(21)
  • Spring Security OAuth2 遠(yuǎn)程命令執(zhí)行漏洞

    Spring Security OAuth2 遠(yuǎn)程命令執(zhí)行漏洞

    cd vulhub/spring/CVE-2016-4977/ docker-compose up -d 訪問 http://192.168.10.171:8080/oauth/authorize?response_type=${233*233}client_id=acmescope=openidredirect_uri=http://test 用admin:admin登陸 出現(xiàn)以下報(bào)錯,表示漏洞存在(response_type里面的命令執(zhí)行了) poc.py #!/usr/bin/env python message = input(‘Enter message to encode:’) p

    2024年02月09日
    瀏覽(22)
  • 微服務(wù)安全Spring Security Oauth2實(shí)戰(zhàn)

    微服務(wù)安全Spring Security Oauth2實(shí)戰(zhàn)

    Spring Authorization Server 是一個框架,它提供了 OAuth 2.1 和 OpenID Connect 1.0 規(guī)范以及其他相關(guān)規(guī)范的實(shí)現(xiàn)。它建立在 Spring Security 之上,為構(gòu)建 OpenID Connect 1.0 身份提供者和 OAuth2 授權(quán)服務(wù)器產(chǎn)品提供了一個安全、輕量級和可定制的基礎(chǔ)。說白了,Spring Authorization Server 就是一個**認(rèn)

    2024年02月03日
    瀏覽(28)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包