正在尝试使用Spring boot webflux设置基于JWT令牌的身份验证。
Spring boot版本:-2.3.0。生成快照
技术堆栈:-Angular 9,Spring boot 2.3.0。BUILD-SNAPSHOT,Spring Security,Spring Security JWT
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-jwt</artifactId>
<version>1.1.0.RELEASE</version>
</dependency>
GUI基于angular 9并使用基于表单的身份验证。
需要JWT来调用来自角,也需要调用直接到API。
WebSecurityConfig,
@Configuration
@EnableWebFluxSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private AuthenticationManager authenticationManager;
@Autowired
private ServerSecurityContextRepository securityContextRepository;
@Bean
public SecurityWebFilterChain securitygWebFilterChain(ServerHttpSecurity http) {
return http.exceptionHandling().authenticationEntryPoint((swe, e) -> {
return Mono.fromRunnable(() -> {
swe.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED);
});
}).accessDeniedHandler((swe, e) -> {
return Mono.fromRunnable(() -> {
swe.getResponse().setStatusCode(HttpStatus.FORBIDDEN);
});
}).and().csrf().disable().formLogin().disable().httpBasic().disable()
.authenticationManager(authenticationManager).securityContextRepository(securityContextRepository)
.authorizeExchange().pathMatchers(HttpMethod.OPTIONS).permitAll().pathMatchers("/login").permitAll()
.anyExchange().authenticated().and().build();
}
@Bean
public PBKDF2Encoder passwordEncoder() {
return new PBKDF2Encoder();
}
}
PBKDF2编码器,
@Component
public class PBKDF2Encoder implements PasswordEncoder {
@Value("${springbootwebfluxjjwt.password.encoder.secret}")
private String secret;
@Value("${springbootwebfluxjjwt.password.encoder.iteration}")
private Integer iteration;
@Value("${springbootwebfluxjjwt.password.encoder.keylength}")
private Integer keylength;
/**
* More info (https://www.owasp.org/index.php/Hashing_Java)
*
* @param cs password
* @return encoded password
*/
@Override
public String encode(CharSequence cs) {
try {
byte[] result = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA512")
.generateSecret(
new PBEKeySpec(cs.toString().toCharArray(), secret.getBytes(), iteration, keylength))
.getEncoded();
return Base64.getEncoder().encodeToString(result);
} catch (NoSuchAlgorithmException | InvalidKeySpecException ex) {
throw new RuntimeException(ex);
}
}
@Override
public boolean matches(CharSequence cs, String string) {
return encode(cs).equals(string);
}
}
AuthenticationManager,
@Component
public class AuthenticationManager implements ReactiveAuthenticationManager {
@Autowired
private JWTUtil jwtUtil;
@Override
public Mono<Authentication> authenticate(Authentication authentication) {
String authToken = authentication.getCredentials().toString();
String username;
try {
username = jwtUtil.getUsernameFromToken(authToken);
} catch (Exception e) {
username = null;
}
if (username != null && jwtUtil.validateToken(authToken)) {
Claims claims = jwtUtil.getAllClaimsFromToken(authToken);
List<String> rolesMap = claims.get("role", List.class);
List<Role> roles = new ArrayList<>();
for (String rolemap : rolesMap) {
roles.add(Role.valueOf(rolemap));
}
UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
username,
null,
roles.stream().map(authority -> new SimpleGrantedAuthority(authority.name())).collect(Collectors.toList())
);
return Mono.just(auth);
} else {
return Mono.empty();
}
}
}
SecurityContextRepository,
@Component
public class SecurityContextRepository implements ServerSecurityContextRepository {
@Autowired
private AuthenticationManager authenticationManager;
@Override
public Mono<Void> save(ServerWebExchange swe, SecurityContext sc) {
throw new UnsupportedOperationException("Not supported yet.");
}
@Override
public Mono<SecurityContext> load(ServerWebExchange swe) {
ServerHttpRequest request = swe.getRequest();
String authHeader = request.getHeaders().getFirst(HttpHeaders.AUTHORIZATION);
if (authHeader != null && authHeader.startsWith("Bearer ")) {
String authToken = authHeader.substring(7);
Authentication auth = new UsernamePasswordAuthenticationToken(authToken, authToken);
return this.authenticationManager.authenticate(auth).map((authentication) -> {
return new SecurityContextImpl(authentication);
});
} else {
return Mono.empty();
}
}
}
这是正确的方法吗?有没有更好的方法?
我也面临同样的问题,经过大量的研究,我已经做了一个完全功能齐全的演示项目,实现webflux webflux安全其他。。。您可以在此处找到完整的实现:https://github.com/eriknyk/webflux-jwt-security-demo
实施包括:
我收到两个jwt:一个OpenID连接ID令牌(ID\u令牌)和一个访问令牌(Access\u令牌)。OpenID的情况或多或少是清楚的-我可以使用JWKSendpoint验证它:https://smth.com/JWKS. 如例(https://bitbucket.org/b_c/jose4j/wiki/JWT例): 问题是如何继续使用访问令牌。我可以从中提取userId和userDetails
我们希望使用SpringOAuth2JWT令牌支持。我们的架构如下:Spring只提供了一个REST接口,前端由AngularJS构建,AngularJS查询Spring REST接口。出于授权目的,我们的前端团队希望使用JWT。因此,我查看了SpringOAuth2JWT支持,但仍然不知道如何与前端讨论JWT令牌。在阅读了一些教程后,我实现了以下内容: 我不确定工作流程如何。我猜:前端访问/oa
是否可以有一个登录rest服务,该服务使用Spring Security验证容器安全性,如果成功,则返回JWT令牌。然后调用其他服务将使用JWT过滤器。 基本思想是这样的。 我有一个React应用程序,它有一个登录页面。它发送一个带有用户名和密码的登录请求(通过rest服务)。安全性是基于容器的(例如Tomcat用户)。Spring security应该通过容器进行身份验证,如果用户名和密码正确,
我是智威汤逊的新手。我有一个会话创建的endpoint。我的手机应用程序提出了一个请求。目前我有它,这样当用户成功登录时,我会在授权承载头中返回JWT: 然而,从我的客户端阅读这是一个有点棘手的问题。我在JSON响应中返回它安全吗?
基于这篇文章和这个问题,刷新令牌应该是长寿命的,访问令牌应该是短寿命的。我将存储我的刷新令牌超过或等于60天,我的访问令牌20分钟或更多/更少,但永远不会超过一个小时。 我在理解这些令牌的使用时的主要难点是两个令牌的存储方法。我明白,我应该将刷新令牌存储为,使其无法通过脚本访问(XSS攻击),并将访问令牌存储在本地,或,以便在API调用中作为密钥使用。这样做是正确的方法吗?我是否应该按照本文中的建
寻求有关如何进行微服务授权的建议。 我使用spring/spring boot来提供所有的微服务 在使用JWT令牌到达实际微服务之前,我可以通过Spring Cloud网关进行身份验证,但是在授权方面,我不确定如何做到这一点。 我想在内部处理business microservice中每个endpoint的授权。 有没有办法将JWT令牌传递给微服务,或者我需要调用authserver来获取用户中的