Spring Boot OAuth2:从cookie中提取JWT进行身份验证



我正在使用spring-boot为我的应用程序构建一个简单的身份验证过程。我有AuthorizationServerConfig&ResourceServerConfig设置,我的前端是一个SPA。当我点击/oauth/token路由时,我得到了一个以前存储在localStorage中的JWT,当我尝试点击资源服务器路由时,使用这个JWT设置了授权头,一切都正常。

但现在我想用存储在cookie中的JWT进行授权,我如何配置它,使其与我当前的授权/资源服务器配置一起工作?我在谷歌上搜索了一段时间,我能找到的最好的方法是设置一个自定义的令牌提取器,但我不知道如何正确处理,提前谢谢。

--------------更新---------------

我打开了@EnableAuthorizationServer和@EnableResourceServer,EnableResourceServer自动设置了OAuthAuthenticationProcessingFilter,这个过滤器用户承载头验证使用承载令牌提取器从请求头中提取,我查看了源代码,它被硬编码到库中,如何自定义此过滤器以从cookie中提取JWT?

从请求对象读取cookie值并手动解析jwt。这是的样本代码

public Jws<Claims> parseJWT(HttpServletRequest request) {
Cookie cookie =  WebUtils.getCookie(request, "Token cookie name");
if(cookie == null) {
throw new SecurityException("Token not found from cookies");
}
String token  = cookie.getValue();
return Jwts.parser().setSigningKey("your signing Key").parseClaimsJws(token);
}

您可以创建请求过滤器并检查jwt。

JWT有许多实现。我在用这个。io.jsonwebtoken

我正在添加一个Token Helper类,该类具有验证、生成和刷新令牌的方法。您可以关注JWT提取部分。

Jar依赖

<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>

JWT帮助程序类。它包含验证、刷新和生成令牌的方法。

import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Component;
import com.test.dfx.common.TimeProvider;
import com.test.dfx.model.LicenseDetail;
import com.test.dfx.model.User;

@Component
public class TokenHelper {
protected final Log LOGGER = LogFactory.getLog(getClass());
@Value("${app.name}")
private String APP_NAME;
@Value("${jwt.secret}")
public String SECRET;    //  Secret key used to generate Key. Am getting it from propertyfile
@Value("${jwt.expires_in}")
private int EXPIRES_IN;  //  can specify time for token to expire. 
@Value("${jwt.header}")
private String AUTH_HEADER;

@Autowired
TimeProvider timeProvider;
private SignatureAlgorithm SIGNATURE_ALGORITHM = SignatureAlgorithm.HS512;  // JWT Algorithm for encryption

public Date getIssuedAtDateFromToken(String token) {
Date issueAt;
try {
final Claims claims = this.getAllClaimsFromToken(token);
issueAt = claims.getIssuedAt();
} catch (Exception e) {
LOGGER.error("Could not get IssuedDate from passed token");
issueAt = null;
}
return issueAt;
}
public String getAudienceFromToken(String token) {
String audience;
try {
final Claims claims = this.getAllClaimsFromToken(token);
audience = claims.getAudience();
} catch (Exception e) {
LOGGER.error("Could not get Audience from passed token");
audience = null;
}
return audience;
}
public String refreshToken(String token) {
String refreshedToken;
Date a = timeProvider.now();
try {
final Claims claims = this.getAllClaimsFromToken(token);
claims.setIssuedAt(a);
refreshedToken = Jwts.builder()
.setClaims(claims)
.setExpiration(generateExpirationDate())
.signWith( SIGNATURE_ALGORITHM, SECRET )
.compact();
} catch (Exception e) {
LOGGER.error("Could not generate Refresh Token from passed token");
refreshedToken = null;
}
return refreshedToken;
}
public String generateToken(String username) {
String audience = generateAudience();
return Jwts.builder()
.setIssuer( APP_NAME )
.setSubject(username)
.setAudience(audience)
.setIssuedAt(timeProvider.now())
.setExpiration(generateExpirationDate())
.signWith( SIGNATURE_ALGORITHM, SECRET )
.compact();
}

private Claims getAllClaimsFromToken(String token) {
Claims claims;
try {
claims = Jwts.parser()
.setSigningKey(SECRET)
.parseClaimsJws(token)
.getBody();
} catch (Exception e) {
LOGGER.error("Could not get all claims Token from passed token");
claims = null;
}
return claims;
}
private Date generateExpirationDate() {
long expiresIn = EXPIRES_IN;
return new Date(timeProvider.now().getTime() + expiresIn * 1000);
}
public int getExpiredIn() {
return EXPIRES_IN;
}
public Boolean validateToken(String token, UserDetails userDetails) {
User user = (User) userDetails;
final String username = getUsernameFromToken(token);
final Date created = getIssuedAtDateFromToken(token);
return (
username != null &&
username.equals(userDetails.getUsername()) &&
!isCreatedBeforeLastPasswordReset(created, user.getLastPasswordResetDate())
);
}
private Boolean isCreatedBeforeLastPasswordReset(Date created, Date lastPasswordReset) {
return (lastPasswordReset != null && created.before(lastPasswordReset));
}
public String getToken( HttpServletRequest request ) {
/**
*  Getting the token from Authentication header
*  e.g Bearer your_token
*/
String authHeader = getAuthHeaderFromHeader( request );
if ( authHeader != null && authHeader.startsWith("Bearer ")) {
return authHeader.substring(7);
}
return null;
}
public String getAuthHeaderFromHeader( HttpServletRequest request ) {
return request.getHeader(AUTH_HEADER);
}

}

最后是您的控制器类

public void validateToken(HttpServletRequest request) {
Cookie cookie =  WebUtils.getCookie(request, "TOKEN_NAME");
if(cookie == null) {
throw new SecurityException("JWT token missing");
}
String token  = cookie.getValue();  // JWT Token
Claims claims =   TokenHelper.getAllClaimsFromToken(token); // claims will be null if Token is invalid
}

最新更新