欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

使用JWT作為Spring?Security?OAuth2的token存儲(chǔ)問(wèn)題

 更新時(shí)間:2021年12月24日 10:51:12   作者:東北小狐貍  
這篇文章主要介紹了使用JWT作為Spring?Security?OAuth2的token存儲(chǔ),大家經(jīng)常使用的方法有兩種一種是使用JWT作為T(mén)oken傳遞,一種是使用Redis存儲(chǔ)Token,資源服務(wù)器本地訪問(wèn)Redis校驗(yàn)Token,需要的朋友可以參考下

Spring Security OAuth2的demo在前幾篇文章中已經(jīng)講過(guò)了,在那些模式中使用的都是RemoteTokenService調(diào)用授權(quán)服務(wù)器來(lái)校驗(yàn)token,返回校驗(yàn)通過(guò)的用戶(hù)信息供上下文中獲取

這種方式會(huì)加重授權(quán)服務(wù)器的負(fù)載,你想啊,當(dāng)用戶(hù)沒(méi)授權(quán)時(shí)候獲取token得找授權(quán)服務(wù)器,有token了訪問(wèn)資源服務(wù)器還要訪問(wèn)授權(quán)服務(wù)器,相當(dāng)于說(shuō)每次請(qǐng)求都要訪問(wèn)授權(quán)服務(wù)器,這樣對(duì)授權(quán)服務(wù)器的負(fù)載會(huì)很大

常規(guī)的方式有兩種來(lái)解決這個(gè)問(wèn)題:

  • 使用JWT作為T(mén)oken傳遞
  • 使用Redis存儲(chǔ)Token,資源服務(wù)器本地訪問(wèn)Redis校驗(yàn)Token

使用JWT與Redis都可以在資源服務(wù)器中進(jìn)行校驗(yàn)Token,從而減少授權(quán)服務(wù)器的工作量

JWT默認(rèn)使用HMACSHA256對(duì)稱(chēng)加密算法,以下記錄下默認(rèn)算法實(shí)現(xiàn)與非對(duì)稱(chēng)RSA算法的集成,使用不同算法加解密測(cè)試方法是一致的,所以放在文章最后

授權(quán)服務(wù)器整合JWT——對(duì)稱(chēng)加解密算法

授權(quán)服務(wù)器整體代碼結(jié)構(gòu)

pom.xml中引入依賴(lài)

<dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>        
		<!-- Spring Security OAuth2 -->
        <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.4.0.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.security</groupId>
            <artifactId>spring-security-jwt</artifactId>
            <version>1.1.0.RELEASE</version>
        </dependency>

SecurityConfig配置,主要需要顯式聲明AuthenticationManager和UserDetailsService這兩個(gè)bean

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Bean
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

    @Bean
    public UserDetailsService userDetailsService(){ //主要是配置這個(gè)Bean,用于授權(quán)服務(wù)器配置中注入
        return super.userDetailsService();
    }

    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // @formatter: off
        auth.inMemoryAuthentication()
                .withUser("hellxz")
                .password(passwordEncoder().encode("xyz"))
                .authorities(Collections.emptyList());
        // @formatter: on
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated() //所有請(qǐng)求都需要通過(guò)認(rèn)證
                .and()
                .httpBasic() //Basic提交
                .and()
                .csrf().disable(); //關(guān)跨域保護(hù)
    }
}

授權(quán)服務(wù)器配置AuthorizationConfig

@Configuration
@EnableAuthorizationServer //開(kāi)啟授權(quán)服務(wù)
public class AuthorizationConfig extends AuthorizationServerConfigurerAdapter {

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    public UserDetailsService userDetailsService;

    @Autowired
    private PasswordEncoder passwordEncoder;

    @Override
    public void configure(AuthorizationServerSecurityConfigurer security) throws Exception {
        //允許表單提交
        security.allowFormAuthenticationForClients()
                .checkTokenAccess("permitAll()")
                .tokenKeyAccess("permitAll()");
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        // @formatter: off
        clients.inMemory()
                .withClient("client-a") //client端唯一標(biāo)識(shí)
                    .secret(passwordEncoder.encode("client-a-secret")) //client-a的密碼,這里的密碼應(yīng)該是加密后的
                    .authorizedGrantTypes("authorization_code", "password", "refresh_token") //授權(quán)模式標(biāo)識(shí),這里主要測(cè)試用password模式,另外refresh_token不是一種模式,但是可以使用它來(lái)刷新access_token(在它的有效期內(nèi))
                    .scopes("read_user_info") //作用域
                    .resourceIds("resource1") //資源id,如不需限制資源id,注釋此處即可
                    .redirectUris("http://localhost:9001/callback"); //回調(diào)地址

        // @formatter: on
    }

    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.authenticationManager(authenticationManager)
                .userDetailsService(userDetailsService)
                .tokenStore(jwtTokenStore()) //設(shè)置jwtToken為tokenStore
                .accessTokenConverter(jwtAccessTokenConverter());//設(shè)置access_token轉(zhuǎn)換器
    }

    /**
     * jwt訪問(wèn)token轉(zhuǎn)換器
     */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("my-sign-key"); //資源服務(wù)器需要配置此選項(xiàng)方能解密jwt的token
        return converter;
    }

    /**
     * jwt的token存儲(chǔ)對(duì)象
     */
    @Bean
    public JwtTokenStore jwtTokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter());
    }
}

這里主要是在configure(AuthorizationServerEndpointsConfigurer endpoints)授權(quán)服務(wù)的端點(diǎn)配置中加入JWT的tokenStore和access_token的轉(zhuǎn)換器,以及這二者的聲明Bean方法

這里使用的是默認(rèn)對(duì)稱(chēng)MAC算法,即加密解密使用相同的密鑰

啟動(dòng)類(lèi)就不說(shuō)了,開(kāi)啟@SpringBootApplicatin的main方法

資源服務(wù)器整合JWT——對(duì)稱(chēng)加解密算法

資源服務(wù)器主要就一個(gè)資源配置類(lèi)

@Configuration
@EnableResourceServer
public class ResourceConfig extends ResourceServerConfigurerAdapter {

    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        //設(shè)置創(chuàng)建session策略
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
        //@formatter:off
        //所有請(qǐng)求必須授權(quán)
        http.authorizeRequests()
                .anyRequest().authenticated();
        //@formatter:on
    }

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
    	//@formatter:off
    	//如不需要限制資源id,請(qǐng)?jiān)谑跈?quán)配置處去除resourceIds的配置
    	resources.resourceId("resource1")
        		 .tokenStore(jwtTokenStore());
    	//@formatter:on
    }

    /**
     * jwt訪問(wèn)token轉(zhuǎn)換器
     */
    @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("my-sign-key"); //與授權(quán)服務(wù)器相同的signingKey
        return converter;
    }

    /**
     * jwt的token存儲(chǔ)對(duì)象
     */
    @Bean
    public JwtTokenStore jwtTokenStore(){
        return new JwtTokenStore(jwtAccessTokenConverter());
    }
}

配置JWT的TokenStore和AccessTokenConverter與授權(quán)服器相同,添加啟動(dòng)類(lèi)完成配置

OAuth整合JWT——非對(duì)稱(chēng)加解密RSA

本部分基于對(duì)稱(chēng)加密部分,僅展示需要修改的部分

首先使用keytool生成jks (Java Key Store) 密鑰,按提示輸入姓氏等信息

keytool -genkeypair -alias hellxz-jwt -validity 3650 -keyalg RSA -keypass hellxzTest -keystore hellxz-jwt.jks -storepass hellxzTest

生成的私鑰文件會(huì)在當(dāng)前目錄,把hellxz-jwt.jks復(fù)制到授權(quán)服務(wù)器的resources目錄下
授權(quán)服務(wù)器需修改jwtAccessTokenConverter()

 @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        KeyStoreKeyFactory storeKeyFactory = new KeyStoreKeyFactory(
                new ClassPathResource("hellxz-jwt.jks"), "hellxzTest".toCharArray());
        converter.setKeyPair(storeKeyFactory.getKeyPair("hellxz-jwt"));
        return converter;
    }

在hellxz-jwt.jks同目錄下,執(zhí)行命令生成公鑰

? keytool -list -rfc --keystore hellxz-jwt.jks | openssl x509 -inform pem -pubkey

輸入密鑰庫(kù)口令:? hellxzTest

-----BEGIN PUBLIC KEY-----

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxU7zulFUVBXmZD28xwM4

ul5e9yFrToLgWKHlNLlp904/GbiWBoZ4tcBcNq3VxLGBN9VOqfP1P5C7fRgz95UI

7ShKCKgsFFGL2rAqsplMDClN/adfsxmpF06rVIkGgce9tR0Q0iONcaN+b/lArK4T

Au76QsQwn9MLXlznVfczclZOZSfDNju+1JuBzqt6fEPWqalBUVYdV0zCUDG8ikN1

l9D0m1tSSaKpiTrU2yEUGUji+79Ury7Y8BClEX6d4CTl9TQAhL5g32GoJEc0S2y+

0bqeqUsv1nUt9KiJT9kiOvA+Q7o2T8OHuqQT9le7kvmIi4gSX5vSNvvZagE2Uglh

zQIDAQAB

-----END PUBLIC KEY-----

-----BEGIN CERTIFICATE-----

MIIDUTCCAjmgAwIBAgIEePeDczANBgkqhkiG9w0BAQsFADBZMQswCQYDVQQGEwJD

TjEQMA4GA1UECBMHYmVpamluZzEQMA4GA1UEBxMHYmVpamluZzEKMAgGA1UEChMB

MDEKMAgGA1UECxMBMDEOMAwGA1UEAxMFemhhbmcwHhcNMTkxMjE1MDUyOTM2WhcN

MjkxMjEyMDUyOTM2WjBZMQswCQYDVQQGEwJDTjEQMA4GA1UECBMHYmVpamluZzEQ

MA4GA1UEBxMHYmVpamluZzEKMAgGA1UEChMBMDEKMAgGA1UECxMBMDEOMAwGA1UE

AxMFemhhbmcwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDFTvO6UVRU

FeZkPbzHAzi6Xl73IWtOguBYoeU0uWn3Tj8ZuJYGhni1wFw2rdXEsYE31U6p8/U/

kLt9GDP3lQjtKEoIqCwUUYvasCqymUwMKU39p1+zGakXTqtUiQaBx721HRDSI41x

o35v+UCsrhMC7vpCxDCf0wteXOdV9zNyVk5lJ8M2O77Um4HOq3p8Q9apqUFRVh1X

TMJQMbyKQ3WX0PSbW1JJoqmJOtTbIRQZSOL7v1SvLtjwEKURfp3gJOX1NACEvmDf

YagkRzRLbL7Rup6pSy/WdS30qIlP2SI68D5DujZPw4e6pBP2V7uS+YiLiBJfm9I2

+9lqATZSCWHNAgMBAAGjITAfMB0GA1UdDgQWBBQF96rK7n0XufnvtJuH9tD9Ixza

6zANBgkqhkiG9w0BAQsFAAOCAQEAuMzWZJhej6+4TGgodQKQ5L5RBtOUbesxA1Ue

s9iA4m/jNZnVCXJE0nY47YVzBCIkIsYALswGooMj1PIJxEMpggXVmIuiJpaPgg+4

sthzISxKzX0ru8IrJTapaglMi74ai6S73LTBSke9GEPgWWnbtdUZoUSiSNt1oJ0J

EhFHdPuzxc36neDFRBOBxW4w3qhsTlKTN2wJm1nLV96nFKmqJhQJhhKt6ihe7hMg

qWxzNsWAqv9gJNdKZt5teqwNKT6H7r1NX5oJkJ0Kn1dZy0O3rDDd5E0KDKkMtwOh

3deJH6Uvtt/dw/drzJlByNDEPp6hYGQu2dW5JG5uiHuzFHnJeA==

-----END CERTIFICATE-----

復(fù)制公鑰部分到public.cert放到資源服務(wù)器的resources目錄

-----BEGIN PUBLIC KEY-----

MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAxU7zulFUVBXmZD28xwM4

ul5e9yFrToLgWKHlNLlp904/GbiWBoZ4tcBcNq3VxLGBN9VOqfP1P5C7fRgz95UI

7ShKCKgsFFGL2rAqsplMDClN/adfsxmpF06rVIkGgce9tR0Q0iONcaN+b/lArK4T

Au76QsQwn9MLXlznVfczclZOZSfDNju+1JuBzqt6fEPWqalBUVYdV0zCUDG8ikN1

l9D0m1tSSaKpiTrU2yEUGUji+79Ury7Y8BClEX6d4CTl9TQAhL5g32GoJEc0S2y+

0bqeqUsv1nUt9KiJT9kiOvA+Q7o2T8OHuqQT9le7kvmIi4gSX5vSNvvZagE2Uglh

zQIDAQAB

-----END PUBLIC KEY-----

修改資源服務(wù)器jwtAccessTokenConverter()方法

  @Bean
    public JwtAccessTokenConverter jwtAccessTokenConverter(){
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        Resource resource = new ClassPathResource("public.cert");
        String publicKey;
        try {
            publicKey = new String(FileCopyUtils.copyToByteArray(resource.getInputStream()));
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
        converter.setVerifierKey(publicKey);
        return converter;
    }

測(cè)試驗(yàn)證

發(fā)送POST請(qǐng)求http://localhost:8080/oauth/token?username=hellxz&password=xyz&scope=read_user_info&grant_type=password

返回結(jié)果

帶token訪問(wèn)資源服務(wù)器

測(cè)試通過(guò)

另外使用JWT應(yīng)設(shè)置盡量短的過(guò)期時(shí)間,因?yàn)镴WT的token無(wú)法手動(dòng)revoke,只能等待其到達(dá)過(guò)期時(shí)間失效

到此這篇關(guān)于使用JWT作為Spring Security OAuth2的token存儲(chǔ)的文章就介紹到這了,更多相關(guān)Spring Security OAuth2 token存儲(chǔ)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java給PDF加水印并合并多個(gè)文件

    Java給PDF加水印并合并多個(gè)文件

    大家好,本篇文章主要講的是Java給PDF加水印并合并多個(gè)文件,感興趣的同學(xué)趕快來(lái)看一看吧,對(duì)你有幫助的話(huà)記得收藏一下
    2022-02-02
  • 解決MyBatis-Plus使用動(dòng)態(tài)表名selectPage不生效的問(wèn)題

    解決MyBatis-Plus使用動(dòng)態(tài)表名selectPage不生效的問(wèn)題

    這篇文章主要介紹了如惡化解決MyBatis-Plus使用動(dòng)態(tài)表名selectPage不生效的問(wèn)題,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-11-11
  • 圖文詳解OkHttp的超時(shí)時(shí)間

    圖文詳解OkHttp的超時(shí)時(shí)間

    HTTP是現(xiàn)代應(yīng)用常用的一種交換數(shù)據(jù)和媒體的網(wǎng)絡(luò)方式,高效地使用HTTP能讓資源加載更快,節(jié)省帶寬,OkHttp是一個(gè)高效的HTTP客戶(hù)端,下面這篇文章主要給大家介紹了關(guān)于OkHttp超時(shí)時(shí)間的相關(guān)資料,需要的朋友可以參考下
    2021-10-10
  • 解讀String字符串拼接的原理

    解讀String字符串拼接的原理

    這篇文章主要介紹了關(guān)于String字符串拼接的原理,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • MybatisPlus使用@TableId主鍵id自增長(zhǎng)無(wú)效的解決

    MybatisPlus使用@TableId主鍵id自增長(zhǎng)無(wú)效的解決

    本文主要介紹了MybatisPlus使用@TableId主鍵id自增長(zhǎng)無(wú)效的解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • java中Map集合的常用方法總結(jié)大全

    java中Map集合的常用方法總結(jié)大全

    開(kāi)發(fā)中最常用的就是List集合和Map集合,Map集合是基于java核心類(lèi)java.util中的,下面這篇文章主要給大家總結(jié)介紹了關(guān)于java中Map集合的一些常用方法,文中通過(guò)代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2024-01-01
  • idea中啟動(dòng)項(xiàng)目彈出 IDEA out of memory窗口的解決方案

    idea中啟動(dòng)項(xiàng)目彈出 IDEA out of memory窗口的解決方案

    這篇文章主要介紹了idea中啟動(dòng)項(xiàng)目彈出 IDEA out of memory窗口的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2024-01-01
  • Java實(shí)現(xiàn)解出世界最難九宮格問(wèn)題

    Java實(shí)現(xiàn)解出世界最難九宮格問(wèn)題

    這篇文章主要介紹了Java實(shí)現(xiàn)解出世界最難九宮格問(wèn)題,芬蘭數(shù)學(xué)家因卡拉花費(fèi)3個(gè)月設(shè)計(jì)出了世界上迄今難度最大的數(shù)獨(dú)游戲,而且它只有一個(gè)答案,本文使用Java實(shí)現(xiàn)解出,需要的朋友可以參考下
    2015-01-01
  • SpringBoot集成Redis及Redis使用方法

    SpringBoot集成Redis及Redis使用方法

    Redis是現(xiàn)在最受歡迎的NoSQL數(shù)據(jù)庫(kù)之一,Redis是一個(gè)使用ANSI C編寫(xiě)的開(kāi)源、包含多種數(shù)據(jù)結(jié)構(gòu)、支持網(wǎng)絡(luò)、基于內(nèi)存、可選持久性的鍵值對(duì)存儲(chǔ)數(shù)據(jù)庫(kù),這篇文章主要介紹了SpringBoot集成Redis及Redis使用方法,需要的朋友可以參考下
    2023-08-08
  • Java實(shí)現(xiàn)快速排序算法的完整示例

    Java實(shí)現(xiàn)快速排序算法的完整示例

    這篇文章主要給大家介紹了關(guān)于Java實(shí)現(xiàn)快速排序算法的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12

最新評(píng)論