1.前言
spring weblfux最大優(yōu)勢莫過于非阻塞帶來的性能提升,認(rèn)為其也會成為spring系列中最受歡迎的框架之一。
網(wǎng)絡(luò)上大多數(shù)整合的文章還是依賴于Spring Boot +Security和用戶名密碼體系來組成驗證模型。不太適合直接依賴于三方登錄或微信登錄的系統(tǒng)。
2.實現(xiàn)代碼
POM.xml
<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>
2.1 簡單攔截器版本適用于面向用戶端接口
@Configuration
public class JwtWebConfig implements WebFilter {
@Override
public Mono<Void> filter(ServerWebExchange serverWebExchange, WebFilterChain webFilterChain) {
ServerHttpRequest request= serverWebExchange.getRequest();
if(request.getPath().value().contains("login")){
return webFilterChain.filter(serverWebExchange);
}
ServerHttpResponse response=serverWebExchange.getResponse();
String authorization=request.getHeaders().getFirst("Authoriszation");
if(authorization == null || ! authorization.startsWith("Bearer ")){
return this.setErrorResponse(response,"未攜帶token");
}
String token=authorization.substring(7);
try {
serverWebExchange.getAttributes().put("user", Jwt.parseJwt(token));
}catch(Exception e) {
return this.setErrorResponse(response,e.getMessage());
}
return webFilterChain.filter(serverWebExchange);
}
protected Mono<Void> setErrorResponse(ServerHttpResponse response, String message){
response.getHeaders().setContentType(MediaType.APPLICATION_JSON);
JSONObject jsonObject=new JSONObject();
jsonObject.put("status_code",500);
jsonObject.put("data",message);
return response.writeWith(Mono.just(response.bufferFactory().wrap(jsonObject.toString().getBytes())));
}
}
2.2 引入Spring Security 滿足多用戶多權(quán)限
AuthenticationManager.java
AuthenticationManager 負(fù)責(zé)校驗 Authentication 對象。在 AuthenticationManager 的 authenticate 函數(shù)中,開發(fā)人員實現(xiàn)對 Authentication 的校驗邏輯。
@Component
public class AuthenticationManager implements ReactiveAuthenticationManager {
@Override
public Mono<Authentication> authenticate(Authentication authentication) {
String authToekn=authentication.getCredentials().toString();
try {
Claims claims= Jwt.parseJwt(authToekn);
//todo 此處應(yīng)該列出token中攜帶的角色表。
List<String> roles=new ArrayList();
roles.add("user");
Authentication authentication1=new UsernamePasswordAuthenticationToken(
claims.getId(),
null,
roles.stream().map(role->new SimpleGrantedAuthority(role)).collect(Collectors.toList())
);
return Mono.just(authentication1);
} catch (Exception e) {
throw new BadCredentialsException(e.getMessage());
}
}
}
SecurityContextRepository.java
此處用于從請求的信息中載入驗證信息(即將header中的token包裝成Authentication并進(jìn)行驗證)
@Component
public class SecurityContextRepository implements ServerSecurityContextRepository {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public Mono<Void> save(ServerWebExchange serverWebExchange, SecurityContext securityContext) {
return Mono.empty();
}
@Override
public Mono<SecurityContext> load(ServerWebExchange serverWebExchange) {
ServerHttpRequest request = serverWebExchange.getRequest();
String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String authToken = authHeader.substring(7);
Authentication auth = null;
auth = new UsernamePasswordAuthenticationToken(authToken, authToken);
return this.authenticationManager.authenticate(auth).map(SecurityContextImpl::new);
} else {
return Mono.empty();
}
}
}
WebSecurityConfig.java
此處加在過濾鏈
@EnableWebFluxSecurity
@EnableReactiveMethodSecurity
public class WebSecurityConfig {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private SecurityContextRepository securityContextRepository;
@Bean
public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) {
return http
.csrf().disable()
.formLogin().disable()
.httpBasic().disable()
.securityContextRepository(securityContextRepository)
.authorizeExchange()
.pathMatchers(HttpMethod.OPTIONS).permitAll()
.pathMatchers("/user/login").permitAll()
.anyExchange().authenticated()
.and().build();
}
}
3.Test

image.png

image.png
4.總結(jié)
這是一個極簡版的實現(xiàn)。絕對相信簽發(fā)出去的token。
優(yōu)點(diǎn)
- 簡單
- 性能高(驗證不用查數(shù)據(jù)庫同時也帶來了一定的性能的提升。)
缺點(diǎn)
- 無法及時作廢token。因為驗證有效性和時效性。
更多關(guān)于jwt的使用,包括簽發(fā)和驗證可以百度或者看
http://www.itdecent.cn/p/ac6cbad76dd6
引用參考