Spring Boot OAuth2:从cookie中提取JWT进行身份验证 [英] Spring Boot OAuth2: extract JWT from cookie for authentication

查看:235
本文介绍了Spring Boot OAuth2:从cookie中提取JWT进行身份验证的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm using spring boot to build a simple auth process for my app. I have AuthorizationServerConfig & ResourceServerConfig setup, my frontend is a SPA. When I hit /oauth/token route, I got a JWT back which I previously stored in localStorage, and when I try to hit the resource server route, I have authorization header setup with this JWT, everything works.

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

But now I want to do authorization with JWT stored in the cookie, how I can config it so that it works with my current authorization/resource server config? I googled for a while and the best I can find is to set up a customize token extractor, but I'm not sure how to get it right, thank you in advance.

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

-------------- update --------------

我启用了@EnableAuthorizationServer和@EnableResourceServer,并且EnableResourceServer自动设置了OAuthAuthenticationProcessingFilter,此过滤器用户承载标头身份验证使用承载令牌提取器从请求标头中提取,我查看了源代码,并将其硬编码到库中,如何自定义此过滤器以从Cookie中提取JWT?

I have @EnableAuthorizationServer and @EnableResourceServer on, and the EnableResourceServer setup an OAuthAuthenticationProcessingFilter automatically, this filter user bearer header authentication which uses a bearer token extractor to extract from the request header, I looked at the source code, it's hardcoded into the library, how I can customize this filter to extract JWT from the cookie?

推荐答案

JWT有许多实现.正在使用这个. io.jsonwebtoken

There are many implementation for JWT. Am using this. io.jsonwebtoken

我要添加一个令牌助手类,该类具有验证,生成和刷新令牌的方法.您可以专注于JWT提取部分.

I am adding a Token Helper Class which has methods to validate, generate, refresh token. You can focus on the JWT extraction part.

Jar依赖

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

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

JWT Helper Class. It contains methods to validate, refresh, generate token.

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

}

这篇关于Spring Boot OAuth2:从cookie中提取JWT进行身份验证的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆