Spring WebFlux +Security+Jwt (适用于微信开发)

1.前言

spring weblfux最大优势莫过于非阻塞带来的性能提升,认为其也会成为spring系列中最受欢迎的框架之一。

网络上大多数整合的文章还是依赖于Spring Boot +Security和用户名密码体系来组成验证模型。不太适合直接依赖于三方登录或微信登录的系统。

2.实现代码

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 满足多用户多权限

AuthenticationManager.java

AuthenticationManager 负责校验 Authentication 对象。在 AuthenticationManager 的 authenticate 函数中,开发人员实现对 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 此处应该列出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并进行验证)


@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.总结

这是一个极简版的实现。绝对相信签发出去的token。

优点

  • 简单
  • 性能高(验证不用查数据库同时也带来了一定的性能的提升。)

缺点

  • 无法及时作废token。因为验证有效性和时效性。

竟然都看到最后了,给小编点个关注吧,小编还会持续更新的,只收藏不点关注的都是在耍流氓!

发表评论
留言与评论(共有 0 条评论)
   
验证码:

相关文章

推荐文章

'); })();