激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務(wù)器之家:專(zhuān)注于服務(wù)器技術(shù)及軟件下載分享
分類(lèi)導(dǎo)航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術(shù)|正則表達(dá)式|C/C++|IOS|C#|Swift|Android|VB|R語(yǔ)言|JavaScript|易語(yǔ)言|vb.net|

服務(wù)器之家 - 編程語(yǔ)言 - Java教程 - Springboot WebFlux集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的示例

Springboot WebFlux集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的示例

2021-08-31 11:57南瓜慢說(shuō) Java教程

這篇文章主要介紹了Springboot WebFlux集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的示例,幫助大家更好的理解和學(xué)習(xí)使用springboot框架,感興趣的朋友可以了解下

1 簡(jiǎn)介

在之前的文章《Springboot集成Spring Security實(shí)現(xiàn)JWT認(rèn)證》講解了如何在傳統(tǒng)的Web項(xiàng)目中整合Spring Security和JWT,今天我們講解如何在響應(yīng)式WebFlux項(xiàng)目中整合。二者大體是相同的,主要區(qū)別在于Reactive WebFlux與傳統(tǒng)Web的區(qū)別。

2 項(xiàng)目整合

引入必要的依賴(lài):

?
1
2
3
4
5
6
7
8
9
10
11
12
13
<dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<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>

2.1 JWT工具類(lèi)

該工具類(lèi)主要功能是創(chuàng)建、校驗(yàn)、解析JWT。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
@Component
public class JwtTokenProvider {
 
  private static final String AUTHORITIES_KEY = "roles";
 
  private final JwtProperties jwtProperties;
 
  private String secretKey;
 
  public JwtTokenProvider(JwtProperties jwtProperties) {
    this.jwtProperties = jwtProperties;
  }
 
  @PostConstruct
  public void init() {
    secretKey = Base64.getEncoder().encodeToString(jwtProperties.getSecretKey().getBytes());
  }
 
  public String createToken(Authentication authentication) {
 
    String username = authentication.getName();
    Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();
    Claims claims = Jwts.claims().setSubject(username);
    if (!authorities.isEmpty()) {
      claims.put(AUTHORITIES_KEY, authorities.stream().map(GrantedAuthority::getAuthority).collect(joining(",")));
    }
 
    Date now = new Date();
    Date validity = new Date(now.getTime() + this.jwtProperties.getValidityInMs());
 
    return Jwts.builder()
        .setClaims(claims)
        .setIssuedAt(now)
        .setExpiration(validity)
        .signWith(SignatureAlgorithm.HS256, this.secretKey)
        .compact();
 
  }
 
  public Authentication getAuthentication(String token) {
    Claims claims = Jwts.parser().setSigningKey(this.secretKey).parseClaimsJws(token).getBody();
 
    Object authoritiesClaim = claims.get(AUTHORITIES_KEY);
 
    Collection<? extends GrantedAuthority> authorities = authoritiesClaim == null ? AuthorityUtils.NO_AUTHORITIES
        : AuthorityUtils.commaSeparatedStringToAuthorityList(authoritiesClaim.toString());
 
    User principal = new User(claims.getSubject(), "", authorities);
 
    return new UsernamePasswordAuthenticationToken(principal, token, authorities);
  }
 
  public boolean validateToken(String token) {
    try {
      Jws<Claims> claims = Jwts.parser().setSigningKey(secretKey).parseClaimsJws(token);
 
      if (claims.getBody().getExpiration().before(new Date())) {
        return false;
      }
 
      return true;
    } catch (JwtException | IllegalArgumentException e) {
      throw new InvalidJwtAuthenticationException("Expired or invalid JWT token");
    }
  }
 
}

2.2 JWT的過(guò)濾器

這個(gè)過(guò)濾器的主要功能是從請(qǐng)求中獲取JWT,然后進(jìn)行校驗(yàn),如何成功則把Authentication放進(jìn)ReactiveSecurityContext里去。當(dāng)然,如果沒(méi)有帶相關(guān)的請(qǐng)求頭,那可能是通過(guò)其它方式進(jìn)行鑒權(quán),則直接放過(guò),讓它進(jìn)入下一個(gè)Filter。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public class JwtTokenAuthenticationFilter implements WebFilter {
 
  public static final String HEADER_PREFIX = "Bearer ";
 
  private final JwtTokenProvider tokenProvider;
 
  public JwtTokenAuthenticationFilter(JwtTokenProvider tokenProvider) {
    this.tokenProvider = tokenProvider;
  }
 
  @Override
  public Mono<Void> filter(ServerWebExchange exchange, WebFilterChain chain) {
    String token = resolveToken(exchange.getRequest());
    if (StringUtils.hasText(token) && this.tokenProvider.validateToken(token)) {
      Authentication authentication = this.tokenProvider.getAuthentication(token);
      return chain.filter(exchange)
          .subscriberContext(ReactiveSecurityContextHolder.withAuthentication(authentication));
    }
    return chain.filter(exchange);
  }
 
  private String resolveToken(ServerHttpRequest request) {
    String bearerToken = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
    if (StringUtils.hasText(bearerToken) && bearerToken.startsWith(HEADER_PREFIX)) {
      return bearerToken.substring(7);
    }
    return null;
  }
}

2.3 Security的配置

這里設(shè)置了兩個(gè)異常處理authenticationEntryPoint和accessDeniedHandler。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
@Configuration
public class SecurityConfig {
 
  @Bean
  SecurityWebFilterChain springWebFilterChain(ServerHttpSecurity http,
                        JwtTokenProvider tokenProvider,
                        ReactiveAuthenticationManager reactiveAuthenticationManager) {
 
    return http.csrf(ServerHttpSecurity.CsrfSpec::disable)
        .httpBasic(ServerHttpSecurity.HttpBasicSpec::disable)
        .authenticationManager(reactiveAuthenticationManager)
        .exceptionHandling().authenticationEntryPoint(
            (swe, e) -> {
      swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
      return swe.getResponse().writeWith(Mono.just(new DefaultDataBufferFactory().wrap("UNAUTHORIZED".getBytes())));
    })
        .accessDeniedHandler((swe, e) -> {
      swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
      return swe.getResponse().writeWith(Mono.just(new DefaultDataBufferFactory().wrap("FORBIDDEN".getBytes())));
    }).and()
        .securityContextRepository(NoOpServerSecurityContextRepository.getInstance())
        .authorizeExchange(it -> it
            .pathMatchers(HttpMethod.POST, "/auth/login").permitAll()
            .pathMatchers(HttpMethod.GET, "/admin").hasRole("ADMIN")
            .pathMatchers(HttpMethod.GET, "/user").hasRole("USER")
            .anyExchange().permitAll()
        )
        .addFilterAt(new JwtTokenAuthenticationFilter(tokenProvider), SecurityWebFiltersOrder.HTTP_BASIC)
        .build();
  }
 
 
  @Bean
  public ReactiveAuthenticationManager reactiveAuthenticationManager(CustomUserDetailsService userDetailsService,
                                    PasswordEncoder passwordEncoder) {
    UserDetailsRepositoryReactiveAuthenticationManager authenticationManager = new UserDetailsRepositoryReactiveAuthenticationManager(userDetailsService);
    authenticationManager.setPasswordEncoder(passwordEncoder);
    return authenticationManager;
  }
}

2.4 獲取JWT的Controller

先判斷對(duì)用戶(hù)密碼進(jìn)行判斷,如果正確則返回對(duì)應(yīng)的權(quán)限用戶(hù),根據(jù)用戶(hù)生成JWT,再返回給客戶(hù)端。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@RestController
@RequestMapping("/auth")
public class AuthController {
 
  @Autowired
  ReactiveAuthenticationManager authenticationManager;
 
  @Autowired
  JwtTokenProvider jwtTokenProvider;
 
  @PostMapping("/login")
  public Mono<String> login(@RequestBody AuthRequest request) {
    String username = request.getUsername();
    Mono<Authentication> authentication = authenticationManager.authenticate(new UsernamePasswordAuthenticationToken(username, request.getPassword()));
 
    return authentication.map(auth -> jwtTokenProvider.createToken(auth));
  }
}

3 總結(jié)

其它與之前的大同小異,不一一講解了。

代碼請(qǐng)查看:https://github.com/LarryDpk/pkslow-samples

以上就是Springboot WebFlux集成Spring Security實(shí)現(xiàn)JWT認(rèn)證的示例的詳細(xì)內(nèi)容,更多關(guān)于Springboot WebFlux集成Spring Security的資料請(qǐng)關(guān)注服務(wù)器之家其它相關(guān)文章!

原文鏈接:https://www.pkslow.com/archives/springboot-spring-security-jwt-webflux

延伸 · 閱讀

精彩推薦
  • Java教程小米推送Java代碼

    小米推送Java代碼

    今天小編就為大家分享一篇關(guān)于小米推送Java代碼,小編覺(jué)得內(nèi)容挺不錯(cuò)的,現(xiàn)在分享給大家,具有很好的參考價(jià)值,需要的朋友一起跟隨小編來(lái)看看吧...

    富貴穩(wěn)中求8032021-07-12
  • Java教程Java實(shí)現(xiàn)搶紅包功能

    Java實(shí)現(xiàn)搶紅包功能

    這篇文章主要為大家詳細(xì)介紹了Java實(shí)現(xiàn)搶紅包功能,采用多線程模擬多人同時(shí)搶紅包,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙...

    littleschemer13532021-05-16
  • Java教程20個(gè)非常實(shí)用的Java程序代碼片段

    20個(gè)非常實(shí)用的Java程序代碼片段

    這篇文章主要為大家分享了20個(gè)非常實(shí)用的Java程序片段,對(duì)java開(kāi)發(fā)項(xiàng)目有所幫助,感興趣的小伙伴們可以參考一下 ...

    lijiao5352020-04-06
  • Java教程Java8中Stream使用的一個(gè)注意事項(xiàng)

    Java8中Stream使用的一個(gè)注意事項(xiàng)

    最近在工作中發(fā)現(xiàn)了對(duì)于集合操作轉(zhuǎn)換的神器,java8新特性 stream,但在使用中遇到了一個(gè)非常重要的注意點(diǎn),所以這篇文章主要給大家介紹了關(guān)于Java8中S...

    阿杜7472021-02-04
  • Java教程升級(jí)IDEA后Lombok不能使用的解決方法

    升級(jí)IDEA后Lombok不能使用的解決方法

    最近看到提示IDEA提示升級(jí),尋思已經(jīng)有好久沒(méi)有升過(guò)級(jí)了。升級(jí)完畢重啟之后,突然發(fā)現(xiàn)好多錯(cuò)誤,本文就來(lái)介紹一下如何解決,感興趣的可以了解一下...

    程序猿DD9332021-10-08
  • Java教程Java BufferWriter寫(xiě)文件寫(xiě)不進(jìn)去或缺失數(shù)據(jù)的解決

    Java BufferWriter寫(xiě)文件寫(xiě)不進(jìn)去或缺失數(shù)據(jù)的解決

    這篇文章主要介紹了Java BufferWriter寫(xiě)文件寫(xiě)不進(jìn)去或缺失數(shù)據(jù)的解決方案,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望...

    spcoder14552021-10-18
  • Java教程Java使用SAX解析xml的示例

    Java使用SAX解析xml的示例

    這篇文章主要介紹了Java使用SAX解析xml的示例,幫助大家更好的理解和學(xué)習(xí)使用Java,感興趣的朋友可以了解下...

    大行者10067412021-08-30
  • Java教程xml與Java對(duì)象的轉(zhuǎn)換詳解

    xml與Java對(duì)象的轉(zhuǎn)換詳解

    這篇文章主要介紹了xml與Java對(duì)象的轉(zhuǎn)換詳解的相關(guān)資料,需要的朋友可以參考下...

    Java教程網(wǎng)2942020-09-17
主站蜘蛛池模板: 欧洲色阁中文字幕 | 欧美成人精品不卡视频在线观看 | 国产在线精品一区二区夜色 | 免费毛片观看 | 免费日韩片 | av亚洲在线观看 | 久久综合婷婷香五月 | 泰剧19禁啪啪无遮挡大尺度 | 免费黄色欧美视频 | 在线观看免费污视频 | 18欧美性xxxx极品hd | 国产精品美女久久久免费 | 日本在线观看视频网站 | 得得啪在线 | 免费看性xxx高清视频自由 | 请播放一级毛片 | 日韩视频精品一区 | 强伦女教师视频 | 久久久久国产一区二区三区不卡 | 久久吊 | 欧美一级精品片在线看 | 91精品国产综合久久婷婷香蕉 | 亚洲一区免费观看 | 美女毛片在线观看 | 又黄又爽又色无遮挡免费 | 久久久久一区二区三区四区五区 | 国产九九热视频 | 国产精品久久久乱弄 | 国产九九在线视频 | 一级小毛片 | 欧美一级做一级爱a做片性 久久久资源网 | 综合国产一区 | 最新中文字幕第一页视频 | 91在线视频在线观看 | 最新av网址在线观看 | 2021狠狠操 | chinese乱子伦xxxx国语对白 | 久草热久草视频 | 一级毛片在线免费观看视频 | 国产精品欧美久久久久一区二区 | 中国av免费观看 |