springboot項目使用jwt生成token

前言

後端是springcloud,前端是用react寫的,以前用過session或者redis保存登陸態,聽了一位朋友的推薦,使用jwt作token校驗前端

portal

portal項目負責用戶登陸第三方綁定等用戶相關功能react

引入jar包

<dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-api</artifactId>
            <version>0.10.5</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-impl</artifactId>
            <version>0.10.5</version>
            <scope>runtime</scope>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt-jackson</artifactId>
            <version>0.10.5</version>
            <scope>runtime</scope>
        </dependency>
複製代碼

建立util

@Component
@Data
@ConfigurationProperties("jwt")
public class JWTUtil {
    private String issuer;
    private String subject;
    private String audience;
    private String alg;
    private String typ;
    private int expire;
    /**
     *@author: zh
     *@date: 2019-04-28 14:56
     *@desc  生成token
     *@param
     *@return
     */
    public String createToken(Map claims) {
        try {
            Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
            Map header=new HashMap();
            header.put("alg", alg);
            header.put("typ", typ);
            Date nowDate = new Date();
            Date expireDate = getAfterDate(nowDate,0,0,0,0,expire,0);//30分鐘過時
            String token = Jwts.builder()
                    .setHeader(header)
                    .setIssuer(issuer)
                    .setSubject(subject)
                    .setAudience(audience)
                    .setClaims(claims)
                    .setExpiration(expireDate)
                    .setIssuedAt(nowDate)
                    .setId(UUID.randomUUID().toString())
                    .signWith(key)
                    .compact();
            return token;
        } catch (JwtException exception){
            exception.printStackTrace();
            throw new BizException(BizStatu.CREATE_TOKEN_FAILED);
        }
    }


    public  Date getAfterDate(Date date, int year, int month, int day, int hour, int minute, int second){
        if(date == null){
            date = new Date();
        }

        Calendar cal = new GregorianCalendar();

        cal.setTime(date);
        if(year != 0){
            cal.add(Calendar.YEAR, year);
        }
        if(month != 0){
            cal.add(Calendar.MONTH, month);
        }
        if(day != 0){
            cal.add(Calendar.DATE, day);
        }
        if(hour != 0){
            cal.add(Calendar.HOUR_OF_DAY, hour);
        }
        if(minute != 0){
            cal.add(Calendar.MINUTE, minute);
        }
        if(second != 0){
            cal.add(Calendar.SECOND, second);
        }
        return cal.getTime();
    }
    /**
     *@author: zh
     *@date: 2019-04-28 14:56
     *@desc  token校驗
     *@param
     *@return
     */
    public void verifyToken(int userId,String token) {
        Claims claims=null;
        Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);
        try {
            claims = Jwts.parser()
                    .setSigningKey(key)
                    .parseClaimsJws(token)
                    .getBody();
            if(claims==null){
                throw new BizException(BizStatu.CLAIMS_IS_NOT_DEFINED);
            }
            if(claims.getAudience()==null||!audience.equals(claims.getAudience())){
                throw new BizException(BizStatu.TOKEN_IS_WRONG);
            }
            if(claims.getIssuer()==null||!issuer.equals(claims.getIssuer())){
                throw new BizException(BizStatu.TOKEN_IS_WRONG);
            }
            if(claims.getSubject()==null||!subject.equals(claims.getSubject())){
                throw new BizException(BizStatu.TOKEN_IS_WRONG);
            }
            if(claims.get("userId")==null||userId!=claims.get("userId",Integer.class)){
                throw new BizException(BizStatu.TOKEN_IS_WRONG);
            }
            if(claims.getExpiration()==null|| DateUtil.compare_date(new Date(),claims.getExpiration())>0){
                throw new BizException(BizStatu.TOKEN_EXPIRED);
            }
        }catch (JwtException ex) {
            ex.printStackTrace();
        }
    }

}
複製代碼

登陸調用

Long userId=user.getLong("id");
        Map claims=new HashMap();
        claims.put("userId",userId);
        String token= jwtUtil.createToken(claims);
複製代碼

gateway過濾

@Component
public class TokenFilter implements GatewayFilter, Ordered {
    @Autowired
    private JWTUtil jwtUtil;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        HttpHeaders headers = request.getHeaders();
        String token = headers.getFirst("token");
        String userId = headers.getFirst("userId");
        if (token==null||"".equals(token.trim()) ||userId==null||"".equals(userId.trim()) ) {
            throw new BizException(401,"缺乏受權token");
        }
        long id;
        try {
            id = Long.parseLong(userId);
        }catch (NumberFormatException e){
            throw new BizException(BizStatu.USERID_IS_NOT_DEFINED);
        }
        jwtUtil.verifyToken(id,token);


        return chain.filter(exchange);
    }

    @Override
    public int getOrder() {
        return 0;
    }
}
複製代碼

token刷新

我這個是朋友合做的項目,寫的也很簡單,登陸受權30分鐘,當用戶在20分鐘以後走網關並且token沒到過時時間,這邊會生成一個新的token放入到用戶header,前端這邊寫一個過濾器,當返回的header中有token且與本地token不一致,替換掉本地token。這樣就能夠懶得寫中間件刷新token了,用得少,只是併發測試沒作,還須要多考慮點東西web

相關文章
相關標籤/搜索