我实现了一个接受JWT作为请求参数的API,并在身份验证时返回一个新的JWT。
@RequestMapping(value = "/authenticate/token", method = RequestMethod.POST,
consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE,
produces = MediaType.APPLICATION_JSON_VALUE)
@Timed
public ResponseEntity authenticate(@RequestParam("login_token") final String token, HttpServletResponse response) {
LOG.debug("Request to login with token : {}", token);
try {
String jwt = authService.loginByToken(token);
response.addHeader(JWTConfigurer.AUTHORIZATION_HEADER, "Bearer " + jwt);
return ResponseEntity.ok(new IdentityToken(jwt));
} catch (AuthenticationException ae) {
LOG.trace("Authentication exception trace: {}", ae);
return new ResponseEntity<>(Collections.singletonMap("AuthenticationException",
ae.getLocalizedMessage()), HttpStatus.UNAUTHORIZED);
}
}
我的loginByToken实现如下所示
@Override public String loginByToken(String token) {
if (!tokenProvider.validateToken(token)) {
throw new BadCredentialsException("Token is invalid.");
}
SecureToken secureToken = tokenProvider.parseJwtToken(token);
User user = userRepository.findByEmail(secureToken.getEmail());
// TODO: Check Account Status is valid, User status is valid
Calendar c = Calendar.getInstance();
c.setTime(new Date());
c.add(Calendar.DATE, Constants.PASSWORD_EXPIRY_DAYS);
if (user.getPasswordExpiryDt() != null
&& user.getPasswordExpiryDt().after(c.getTime())) {
throw new BadCredentialsException("Password changed");
}
// TODO: Find how to create authentication object and return ID token.
// return tokenProvider.createToken(authentication, false);
return token;
}
此时,我不确定如何创建一个身份验证对象,其中包含我可以传递给创建身份令牌的createToken
函数的所有用户详细信息。
这是我的项目,没有这篇文章中提到的更改 - https://github.com/santoshkt/ngx-pipes-test。
我已阅读有关匿名身份验证,PreAuthenticated等但不确定如何处理此案例。将不胜感激如何做到这一点。
答案 0 :(得分:1)
如果您想使用Spring Security,您可能不应该使用Spring MVC端点来处理(预)身份验证。
在您的情况下,您可能希望更改Spring安全配置,以便它具有从请求参数中获取令牌的过滤器以及从令牌中检索用户/身份验证对象的身份验证提供程序:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.antMatcher("/authenticate/token")
.authorizeRequests()
.anyRequest().authenticated()
.and()
// This is a filter bean you'll have to write
.addFilterBefore(filter(), RequestHeaderAuthenticationFilter.class)
// This is your token verifier/decoder
.authenticationProvider(authenticationProvider())
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS);
}
对于过滤器,您可以从AbstractPreAuthenticatedProcessingFilter
延伸并使其返回login_token
参数。在这里,您必须实现两个方法getPreAuthenticatedPrincipal()
和getPreAuthenticatedCredentials()
。
@Override
protected Object getPreAuthenticatedPrincipal(HttpServletRequest request) {
// You could already decode your token here to return your username
return request.getParameter("login_token");
}
@Override
protected Object getPreAuthenticatedCredentials(HttpServletRequest request) {
return request.getParameter("login_token");
}
您的身份验证提供程序应为PreAuthenticatedAuthenticationProvider
类型,此处您可以设置AuthenticationUserDetailsService
:
@Bean
public AuthenticationProvider authenticationProvider() {
PreAuthenticatedAuthenticationProvider provider = new PreAuthenticatedAuthenticationProvider();
// service is a bean of type AuthenticationUserDetailsService
// You could autowire this in your security configuration class
provider.setPreAuthenticatedUserDetailsService(service);
return provider;
}
现在,您可以创建自己的AuthenticationUserDetailsService
以根据您的令牌检索UserDetails
对象:
@Service
public class TokenAuthenticationUserDetailsService implements AuthenticationUserDetailsService<PreAuthenticatedAuthenticationToken> {
@Override
public UserDetails loadUserDetails(PreAuthenticatedAuthenticationToken authentication) throws UsernameNotFoundException {
// In this case the authentication.getCredentials() will contain your token and you can return a UserDetails object
return new User(/** ... */);
}
}
答案 1 :(得分:0)
由于您要为JWT令牌请求提供HTML页面,最好的方法是创建自己的Spring Security Custom Entry Point 您可以查看示例here
如果是管理身份验证的另一个系统,并且您只想管理授权,则可以“信任”另一个系统,然后管理您自己的授权;在这种情况下,您可以使用here所述的PreAuthentication Scenario
;你可以找到一个样本here
我希望它有用