SpringCloudAlibabaマイクロサービスコンバット17-JWT認定

概要概要

システムがOAuth2認証トークン情報を2つのカテゴリに返した後:不透明トークン(不透明トークン)透明トークン(不透明トークンではない)。

不透明なトークンは、読み取り不可能なトークンの一種であり、一般的に言えば、通常のUUID文字列です。不透明なトークンを使用すると、リソースサービスはトークンが何であり、誰を表すかを認識しないため、システムのパフォーマンスと可用性が低下し、遅延が増加します。認証サーバーを呼び出して、トークンが誰であるかを知るためのユーザー情報インターフェイスを取得する必要があります。 。
以下は、リソースサーバーでの構成です。認証サーバーのインターフェイスアドレスを指定する必要があります。

security:
  oauth2:
    resource:
      user-info-uri: http://localhost:5000/user/current/get
      id: account-service

透過トークンの典型的な代表はJWTです。ユーザー情報はJWT文字列に格納されます。リソースサーバーはトークン自体を解析できるため、トークンを検証するために認証サーバーにアクセスする必要がなくなります。

前の章では、不透明なトークンaccess_tokenを使用しましたが、この集中型認証サービスがマイクロサービスシステムのボトルネックになることを考慮して、この章では、jwtを使用して前のaccess_token、特別な(zhuang)業界(bi)ポイントを置き換えます。分散化と呼ばれます。

ふりをする

jwtとは

Json Webトークン(JWT)は、JSONに基づくオープンスタンダード(RFC 7519)であり、Webアプリケーション環境間でクレームを転送するために実装されています。トークンはコンパクトで安全になるように設計されており、分散サイトのシングルサインオン(SSO)シナリオに特に適しています。JWT宣言は通常、認証されたユーザーID情報をIDプロバイダーとサービスプロバイダーの間で転送するために使用されます。これにより、リソースサーバーからリソースを取得したり、他のビジネスロジックに必要な宣言情報を追加したりできます。トークンは次のとおりです。また、認証に直接使用することも、暗号化することもできます。

簡単に言えば、これは固定形式の文字列であり、通常は暗号化されています。

ヘッダー、ペイロード、署名の3つの部分で構成され、これら3つの部分はすべてjson形式です。

  • ヘッダー:JSONは、タイプや署名アルゴリズムなど、JWTの基本情報を記述します。Base64を使用して文字列としてエンコードする
  • ペイロード:JWT情報はJSON形式で記述されます。標準の定義に加えて、カスタム情報を追加することもできます。また、Base64エンコーディングを文字列として使用します。
    1. iss:発行者
    2. サブ:ユーザー
    3. aud:レシーバー
    4. exp(expires):UNIXタイムスタンプで記述された有効期限
    5. iat(発行日):unixタイムスタンプで記述された発行時刻
  • 署名:最初の2つの文字列を連結した後、ヘッダーで定義された暗号化アルゴリズムを使用し、キーを使用して署名し、署名情報を最後に追加します。

JWTは対称暗号化キーを使用できますが、非対称キーを使用する方が安全です。この記事では対称暗号化を使用します。

コードの変更

データベース

最初にaccess_tokenを使用したとき、oauth2に関連する7つのデータテーブルを作成しました

ここに画像の説明を挿入

jwtを使用する場合は、クライアント情報をデータベースに保存するだけでよいため、データテーブルoauth_client_detailsを保持するだけで済みます。
ここに画像の説明を挿入

他のデータテーブルは不要になり、削除できます。

認証サービスAuthorizationServerConfig

  1. AuthorizationServerConfigTokenStore構成を変更します
@Bean
public TokenStore tokenStore() {
    
    
    //return new JdbcTokenStore(dataSource);
        return new JwtTokenStore(jwtTokenEnhancer());
}


/**
 * JwtAccessTokenConverter
 * TokenEnhancer的子类,帮助程序在JWT编码的令牌值和OAuth身份验证信息之间进行转换。
 */
 @Bean
 public JwtAccessTokenConverter jwtTokenEnhancer(){
    
    
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        // 设置对称签名
        converter.setSigningKey("javadaily");
        return converter;
}

以前は、access_tokenをデータベースに保存していましたが、jwtを使用した後は、データベースに保存する必要がなくなったため、保存方法を変更する必要があります。

jwtは暗号化アルゴリズム署名を使用した情報を必要とします。ここでは、最初の対称秘密鍵(javadaily)を使用してトークンに署名します。もちろん、サーバーリソースも同じ秘密鍵を使用する必要がある対称秘密鍵です。

  1. 変更configure(AuthorizationServerEndpointsConfigurer endpoints)方法、構成jwt
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    
    
        //如果需要使用refresh_token模式则需要注入userDetailService
        endpoints.authenticationManager(this.authenticationManager)
                        .userDetailsService(userDetailService)
                        .tokenStore(tokenStore())
                        .accessTokenConverter(jwtTokenEnhancer());
}

これは主にインジェクションaccessTokenConverter、つまり上記で構成されたトークンコンバーターです。

上記の構成後、認証サーバーはすでにjwtトークンを生成できます。ここでは、最初にPostmanを使用して呼び出し、生成されたjwtトークンを確認します。

ここに画像の説明を挿入

上の図から、jwtトークンが正常に生成されていることがわかり、生成されたjwtトークンをhttps://jwt.io/に移動して分析できます。

我々は非常に世代の理解されていない場合は、ロジックのトークンJWT、することができますDefaultTokenServices#createAccessToken(OAuth2Authentication authentication)し、JwtAccessTokenConverter#enhance(OAuth2AccessToken accessToken, OAuth2Authentication authentication)上のブレークポイントを作成し、コード実行の効果を観察します。

  1. 删除认证服务器提供给资源服务器获取用户信息的接口
/**
 * 获取授权的用户信息
 * @param principal 当前用户
 * @return 授权信息
 */@GetMapping("current/get")
public Principal user(Principal principal){
        return principal;
}

透過トークンjwtトークンを使用した後、リソースサーバーはトークンを直接解析および検証でき、認証サーバーインターフェイスを呼び出す必要がなくなるため、ここで直接削除できます。

  1. jwtトークンの有効期間を変更する(オプション)

    デフォルトの期間は12時間のjwtトークンです。更新トークンは30日間有効です。デフォルトの時間DefaultTokenServicesを変更する場合は、有効時間を挿入して変更できます

@Primary
@Bean
public DefaultTokenServices tokenServices(){
    
    
        DefaultTokenServices tokenServices = new DefaultTokenServices();
        tokenServices.setTokenEnhancer(jwtTokenEnhancer());
        tokenServices.setTokenStore(tokenStore());
        tokenServices.setSupportRefreshToken(true);
        //设置token有效期,默认12小时,此处修改为6小时   21600
        tokenServices.setAccessTokenValiditySeconds(60 * 60 * 6);
        //设置refresh_token的有效期,默认30天,此处修改为7天
        tokenServices.setRefreshTokenValiditySeconds(60 * 60 * 24 * 7);
        return tokenServices;
}

次にconfigure()、tokenServicesメソッドを追加します

@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
    
    
                //如果需要使用refresh_token模式则需要注入userDetailService
        endpoints.authenticationManager(this.authenticationManager)
                        .userDetailsService(userDetailService)
            //注入自定义的tokenservice,如果不使用自定义的tokenService那么就需要将tokenServce里的配置移到这里
                        .tokenServices(tokenServices());
}

リソースサーバーResourceServerConfig

  1. リソースサーバーで構成されている認証サーバーのインターフェイスプロパティを削除します user-info-uri
security:  
  oauth2:    
    resource:      
      id: account-service
  1. TokenStoreとJwtAccessTokenConverterを挿入します
@Bean
public TokenStore tokenStore() {
    
    
        return new JwtTokenStore(jwtTokenEnhancer());
}

@Bean
public JwtAccessTokenConverter jwtTokenEnhancer(){
    
    
        JwtAccessTokenConverter jwtTokenEnhancer = new JwtAccessTokenConverter();
        jwtTokenEnhancer.setSigningKey("javadaily");
        return jwtTokenEnhancer;
}

注:対称暗号化アルゴリズムは、認証サーバーの秘密鍵と一致している必要があります。もちろん、構成ファイルに抽出することもできます。

  1. configure(ResourceServerSecurityConfigurer resources)メソッドの追加、トークン構成の追加
@Override
public void configure(ResourceServerSecurityConfigurer resources) throws Exception {
        resources.resourceId(resourceId)
                        .tokenStore(tokenStore());
}

質問:リソースサーバーがjwtを使用した後、トークンはどこで検証できますか?

アプリケーションに追加@EnableResourceServerFilterChanを追加します春のセキュリティ注釈の後にOAuth2AuthenticationProcessingFilterOAuth2AuthenticationProcessingFilter使用されるOAuth2AuthenticationManagerトークンを検証します。

検証ロジックの主なコード実行シーケンスは次のとおりです。

ここに画像の説明を挿入

OAuth2AuthenticationProcessingFilter#doFilter()検証プロセスを体験するために休憩することをお勧めします

ゲートウェイSecurityConfig

  1. ReactiveJwtAuthenticationManagertokenStoreからロードOAuth2AccessTokenを作成します

元のaccess_tokenはデータベースに保存されているためReactiveJdbcAuthenticationManager、データベースからaccess_tokenを取得するように記述しました。現在はjwtです。同じReactiveJwtAuthenticationManagerコードの関連するクラスjwtも定義する必要があり、ReactiveJdbcAuthenticationManager投稿されなくなりました。

  1. TokenStoreとJwtAccessTokenConverterを挿入します
@Bean  
public TokenStore tokenStore() {
    
    
        return new JwtTokenStore(jwtTokenEnhancer());
}

@Bean  
public JwtAccessTokenConverter jwtTokenEnhancer(){
    
    
        JwtAccessTokenConverter jwtTokenEnhancer = new JwtAccessTokenConverter();
        jwtTokenEnhancer.setSigningKey("javadaily");
        return jwtTokenEnhancer;
}

注:対称暗号化アルゴリズムは、認証サーバーの秘密鍵と一致している必要があります。もちろん、構成ファイルに抽出することもできます。

  1. 修正SecurityConfig#SecurityWebFilterChain()方法、交換ReactiveJdbcAuthenticationManager
ReactiveAuthenticationManager tokenAuthenticationManager 
= new ReactiveJwtAuthenticationManager(tokenStore());

tokenStoreをコンストラクターに渡すだけです。

テスト

自分でテストしてください。

概要

jwtトークンとaccess_tokenの使用の最大の違いは、リソースサーバーがトークンを検証するためにサーバーを認証する必要がなくなったことです。これにより、システムの全体的なパフォーマンスが向上します。jwtを使用した後のプロジェクトのプロセスアーキテクチャは次のとおりです。

ここに画像の説明を挿入

http://javadaily.cn/tags/SpringCloud表示する前に記事の会場になりたい場合は、この一連の記事が最初の19になります。

jwtを使用すると、jwtの長所だけでなく短所も確認する必要があるため、実際のシーンに応じて自由に選択できます。jwtの2つの最大の短所は次のとおりです。

  • Jwtは1回限りです。トークンが発行されると、有効期限が切れる前に有効になり、破棄することはできません。ユーザー権限を途中で変更して情報を更新する必要がある場合、再発行できるのはjwtのみですが、古いjwtは引き続き正常に使用でき、古いjwtを使用して取得した情報は古くなっています。
  • jwtには認証情報が含まれています。リークされると、誰でもトークンのすべての権限を取得できます。流用を防ぐために、jwtの有効時間を長く設定しすぎないようにしてください。

おすすめ

転載: blog.csdn.net/jianzhang11/article/details/107242131