国产成人精品久久免费动漫-国产成人精品天堂-国产成人精品区在线观看-国产成人精品日本-a级毛片无码免费真人-a级毛片毛片免费观看久潮喷

您的位置:首頁技術(shù)文章
文章詳情頁

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

瀏覽:35日期:2023-03-19 11:19:38
1 簡介

在之前的文章《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)目整合

引入必要的依賴:

<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工具類

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

@Componentpublic 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的過濾器

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

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。

@Configurationpublic 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

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

@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é)

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

代碼請查看: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的資料請關(guān)注好吧啦網(wǎng)其它相關(guān)文章!

標(biāo)簽: Spring
相關(guān)文章:
主站蜘蛛池模板: 国产女人伦码一区二区三区不卡 | 国产免费一级片 | 亚洲精品一区二区 | 久99久精品视频免费观看v | 国产三级日本三级日产三 | 国内精品伊人久久久久妇 | 免费观看毛片的网站 | 亚洲精品国产成人专区 | jiucao在线观看精品 | 国内自拍在线观看 | 酒色成人 | 国产美女自拍视频 | 日本美女性爱 | 精品视频免费在线观看 | 5级做人爱c视版免费视频 | 成人性色生活影片 | 国产欧美一区视频在线观看 | 欧美一级毛片怡红院 | 亚洲一区二区精品视频 | 欧美一级毛片一级 | 亚洲天堂在线观看视频 | 亚洲精品不卡视频 | 免看一级一片一在线看 | 欧美xxxxx九色视频免费观看 | 免费亚洲成人 | 国产亚洲一区二区精品 | 成人精品国产亚洲 | 欧美一级aa免费毛片 | 欧美黄色一级视屏 | 欧美片能看的一级毛片 | 久久久成人啪啪免费网站 | 男女视频免费网站 | 久久久久999 | 亚洲国产老鸭窝一区二区三区 | 韩国日本一级毛片免费视频 | 69视频成人| 久久午夜影视 | 怡红院精品视频 | 成人精品第一区二区三区 | 国产成人精品免费 | 日韩精品亚洲人成在线观看 |