JWTに基づく春のセキュリティと権限システム

一つは、シーン

前と分離の終了後に、どのようにデータ交換のセキュリティを確保するには?

SB:トークンうん

クライアントはまた、JSONデータの送信を終了、アプレット、H5などの移動、身元確認の問題もに関連しています

第二に、問題

達成するためにどのように最終的にはトークン、最良の方法はありますか?

誰が((▼はメ▼理解)ロード力。。)百件のプロジェクトをしてきた多くのそのようなプロジェクトが実装されて見てい

  • トークン?私たちは必要ありません。
  • トークンコード化され、そしてクライアントの背景(多くは確かにあります)
  • クライアントに提供されるいくつかのアルゴリズムトークンによって生成されたトークンダイナミック、背景、(この方法では何もないではありませんが、完璧ではありません)
  • 送信を暗号化し、全体JSONデータは、キーバックグラウンドを提供(EM ....評価されていません)

第三に、ソリューション

今日はの使用で説明するためにJWT、トークンは、問題を解決します

JWTの#科学

JSONウェブトークン(JWT)は、ネットワークアプリケーションJSONベースのオープン規格との間の情報転送である(RFC 7519)安全異なるシステム間で情報を伝送するためのJSONオブジェクトとして、。主な使用シナリオは、一般的にアイデンティティで認証されたユーザID情報との間で転送プロバイダを提供し、サービスするために使用されます。

次のようにJWTは、3つの部分、その他で構成されています。

  • ヘッダ(ヘッダ)は、トークンタイプおよび署名アルゴリズムの2つの部分を含んでいます
  • ペイロード(負荷)がより多くのコンテンツ、長いトークン、トークンカスタムコンテンツを運ばれ、データは、base64、非暗号化、ひび割れ、機密情報を格納することはできませんです
  • 署名(署名された)文字列からなるヘッダ+ペイロードが署名を得るために、署名アルゴリズム指定した値によって計算され、サーバは、トークン正当かどうかを決定するために、このフラグによって得ることができます
#説明春のセキュリティ(ボーナス)

JWTトークンがあり春のセキュリティだけでなく、Apacheのシロ権に加えて、当然のことながら、(本当に強い)、多くのユーザー権利の問題を解決するために春のセキュリティモジュールと組み合わせて問題を解決解決することができ、ないセキュリティに強いがあり、フォローアップ記事詳細な比較を書きます2。

第四に、実装

pom.xmlは春のセキュリティに依存し、瓶JWT導入しました

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>
复制代码

JWTツール、トークン生成、検証トークン、および他のさわやかなトークン

@Component
public class JwtTokenUtil {

    private static final String CLAIM_KEY_USERNAME = "sub";
    private static final String CLAIM_KEY_CREATED = "created";
    
    // 生成token
    public String generateToken(UserDetails userDetails) {
        ...
    }
    
    // 刷新token
    public String refreshToken(String token) {
        ...
    }
    
    // 校验token
    public Boolean validateToken(String token, UserDetails userDetails) {
        ...
    }
复制代码

トークントークンフィルタ処理インターフェース

@Component
public class JwtTokenFilter extends OncePerRequestFilter {

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private JwtTokenUtil jwtTokenUtil;

    @Override
    protected void doFilterInternal (HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws ServletException, IOException {
        String authHeader = request.getHeader(Constant.HEADER_STRING );
        if (authHeader != null && authHeader.startsWith(Constant.TOKEN_PREFIX )) {
            final String authToken = authHeader.substring(Constant.TOKEN_PREFIX.length() );
            String username = jwtTokenUtil.getUsernameFromToken(authToken);
            if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) {
                UserDetails userDetails = this.userDetailsService.loadUserByUsername(username);
                if (jwtTokenUtil.validateToken(authToken, userDetails)) {
                    UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(
                            userDetails, null, userDetails.getAuthorities());
                    authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(
                            request));
                    SecurityContextHolder.getContext().setAuthentication(authentication);
                }
            }
        }
        chain.doFilter(request, response);
    }
}
复制代码

春のセキュリティのコアの構成

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled=true, securedEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl userService;

    @Bean
    public JwtTokenFilter authenticationTokenFilterBean() throws Exception {
        return new JwtTokenFilter();
    }

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

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService).passwordEncoder(new BCryptPasswordEncoder());
    }

    @Override
    protected void configure(HttpSecurity httpSecurity) throws Exception {
        String[] urls = new String[]{"/user/login", "/user/register"};
        httpSecurity.csrf().disable()
                .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
                .authorizeRequests()
                // 允许注册和登录接口不需token访问
                .antMatchers(urls).permitAll()
                .anyRequest().authenticated();
        httpSecurity.addFilterBefore(authenticationTokenFilterBean(), UsernamePasswordAuthenticationFilter.class);
        httpSecurity.headers().cacheControl();
    }
}
复制代码
権限のテスト、インターフェースは@PreAuthorizeを追加し、アクセス制限を制限する必要があります
@RestController
public class RoleController {

    /**
     * 测试普通权限
     *
     * @return
     */
    @PreAuthorize("hasAuthority('ROLE_NORMAL')")
    @GetMapping(value="/normal/test")
    public String test1() {
        return "普通角色访问";
    }

    /**
     * 测试管理员权限
     *
     * @return
     */
    @PreAuthorize("hasAuthority('ROLE_ADMIN')")
    @GetMapping(value = "/admin/test")
    public String test2() {
        return "管理员访问";
    }
}
复制代码

以下に示すようにユーザーがアクセスするための役割、ユーザーロールテーブルを追加する必要があります

ユーザーロールテーブル

第五に、テスト結果

  • ログインに成功リターン・トークンの後

  • ベルトトークンがなければ、それはアクセスを拒否されます

  • 正しいアクセス方法

このソースで

おすすめ

転載: juejin.im/post/5d2c958ff265da1b667c0d34