单点登录JWT实现-实战篇

package com.dalingjia.seckill.common.utils;


import com.fasterxml.jackson.databind.ObjectMapper;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jws;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;

import java.util.*;

/**
 * JWT 工具类
 */
@Component
public class JwtTokenUtil {

protected final Logger logger = LoggerFactory.getLogger(this.getClass());
public static final String AUTH_HEADER = "Authorization";
public static final String TOKEN_HEAD = "Bearer ";

private static String secret = "seckill-3600";

private Long expiration = 1*1*60*60l;//默认存储小时  3600秒

public Long getExpiration() {
    return expiration;
}

/**
 * 解析token
 * @param token
 * @return
 */
public static Claims parseToken(String token){
    Jws<Claims> jws = Jwts.parser()
                .setSigningKey(secret)
                .parseClaimsJws(token);
    Claims claims = jws.getBody();
    return claims;
}

/**
 * 创建token
 * @param claims
 * @return
 */
  public static String generateToken(Map<String, Object> claims) {
    return Jwts.builder()
            .setClaims(claims)
            .signWith(SignatureAlgorithm.HS512, secret)
            .compact();
  }

}

package com.dalingjia.seckill.common.interceptor;

import com.dalingjia.seckill.common.Constants;
import com.dalingjia.seckill.common.enums.ResponseCodeEnum;
import com.dalingjia.seckill.common.exceptions.ValidateException;
import com.dalingjia.seckill.common.utils.CommonUtil;
import com.dalingjia.seckill.common.utils.JwtTokenUtil;
import com.dalingjia.seckill.entity.response.CheckAuthResponse;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import lombok.extern.log4j.Log4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.servlet.handler.HandlerInterceptorAdapter;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * Created by ytw83 on 2019/1/1.
 */
@Log4j
public class LoginInterceptor extends HandlerInterceptorAdapter{
private static String SUCCESS = "000000";

@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
    String authHeader = request.getHeader(JwtTokenUtil.AUTH_HEADER);
    boolean isAjax = CommonUtil.isAjax(request);
    if (StringUtils.isEmpty(authHeader)) {
        return response(isAjax,response);
    }
    String accessToken = authHeader.substring(JwtTokenUtil.TOKEN_HEAD.length());
    if (StringUtils.isEmpty(accessToken)) {
        return response(isAjax,response);
    }

    CheckAuthResponse checkAuthResponse = validToken(accessToken);
    if (SUCCESS.equals(checkAuthResponse.getCode())) {
        return super.preHandle(request, response, handler);
    }

    if (isAjax) {
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write("{\"code\":\""+checkAuthResponse.getCode()+"\"" +
                ",\"msg\":\""+checkAuthResponse.getMsg()+"\"}");
        return false;
    }
    response.sendRedirect(Constants.SSO_ACCESS_URL);
    return false;
}


public CheckAuthResponse validToken(String token) {
    CheckAuthResponse response=new CheckAuthResponse();
    try{
        beforeValidateAuth(token);

        Claims claims=JwtTokenUtil.parseToken(token);
        response.setUid(claims.get("uid").toString());
        response.setCode(ResponseCodeEnum.SUCCESS.getCode());
        response.setMsg(ResponseCodeEnum.SUCCESS.getMsg());

    }catch (ExpiredJwtException e){
        log.error("ExpiredJwtException :"+e);
        response.setCode(ResponseCodeEnum.TOKEN_EXPIRE.getCode());
        response.setMsg(ResponseCodeEnum.TOKEN_EXPIRE.getMsg());
    }catch (SignatureException e1){
        log.error("SignatureException :"+e1);
        response.setCode(ResponseCodeEnum.SIGNATURE_ERROR.getCode());
        response.setMsg(ResponseCodeEnum.SIGNATURE_ERROR.getMsg());
    }catch (Exception e){
        log.error("login occur exception :"+e);
        response.setCode(ResponseCodeEnum.SYSTEM_BUSY.getCode());
        response.setMsg(ResponseCodeEnum.SYSTEM_BUSY.getMsg());
    }finally {
        log.info("response:"+response);
    }

    return response;
}

private void beforeValidateAuth(String token){
    if(StringUtils.isEmpty(token)){
        throw new ValidateException("token信息为空");
    }
}

 private boolean response(boolean isAjax,HttpServletResponse response) throws IOException {
    if(isAjax){
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().write("{\"code\":\"-1\",\"msg\":\"error\"}");
        return false;
    }
    response.sendRedirect(Constants.SSO_ACCESS_URL);
    return false;
 }
}



package com.dalingjia.seckill.common.exceptions;

import com.dalingjia.seckill.common.enums.ResponseCodeEnum;

public class ValidateException extends RuntimeException {

/**
 * versionId
 */
private static final long serialVersionUID = 7172827201346602909L;


/**
 * 返回码
 */
private String errorCode;
/**
 * 信息
 */
private String errorMessage;

/**
 * 构造函数
 */
public ValidateException() {
    super();
}

/**
 * 构造函数
 *
 * @param errorCode
 */
public ValidateException(String errorCode) {
    super(errorCode);
    this.errorCode= ResponseCodeEnum.SYS_PARAM_NOT_RIGHT.getCode();
    this.errorMessage= ResponseCodeEnum.SYS_PARAM_NOT_RIGHT.getMsg();
}

/**
 * 构造函数
 *
 * @param cause
 */
public ValidateException(Throwable cause) {
    super(cause);
}

/**
 * 构造函数
 *
 * @param errorCode
 * @param cause
 */
public ValidateException(String errorCode, Throwable cause) {
    super(cause);
    this.errorCode = errorCode;
}

/**
 * 构造函数
 *
 * @param errorCode
 * @param message
 */
public ValidateException(String errorCode, String message) {
    super();
    this.errorCode = errorCode;
    this.errorMessage = message;
}

/**
 * 构造函数
 *
 * @param errorCode
 * @param message
 * @param cause
 */
public ValidateException(String errorCode, String message, Throwable cause) {
    super(cause);
    this.errorCode = errorCode;
    this.errorMessage = message;
}

/**
 * Getter method for property <tt>errorCode</tt>.
 *
 * @return property value of errorCode
 */
public String getErrorCode() {
    return errorCode;
}

/**
 * Setter method for property <tt>errorCode</tt>.
 *
 * @param errorCode value to be assigned to property errorCode
 */
public void setErrorCode(String errorCode) {
    this.errorCode = errorCode;
}

/**
 * Getter method for property <tt>errorMessage</tt>.
 *
 * @return property value of errorMessage
 */
public String getErrorMessage() {
    return errorMessage;
}

/**
 * Setter method for property <tt>errorMessage</tt>.
 *
 * @param errorMessage value to be assigned to property errorMessage
 */
 public void setErrorMessage(String errorMessage) {
    this.errorMessage = errorMessage;
 }

}




package com.dalingjia.seckill.common.enums;


public enum  ResponseCodeEnum {
  USERORPASSWORD_ERRROR("001001","用户名或密码不存在"),
  SUCCESS("000000","成功"),
  SYS_PARAM_NOT_RIGHT("001002","请求参数错误"),
  TOKEN_EXPIRE("001003","token过期"),
  SIGNATURE_ERROR("001004","签名验证失败"),
  QUERY_DATA_NOT_EXIST("001005","请求数据不存在"),
  SYSTEM_BUSY("001099","系统繁忙,请稍候重试");

private final String code;
private final  String msg;

ResponseCodeEnum(String code, String msg) {
    this.code = code;
    this.msg = msg;
}

public String getCode() {
    return code;
}

public String getMsg() {
    return msg;
 }
}




package com.dalingjia.seckill.common.utils;

import org.apache.commons.lang3.StringUtils;

import javax.servlet.http.HttpServletRequest;

/**
 * Created by ytw83 on 2019/1/1.
 */
 public class CommonUtil {
  public static boolean isAjax(HttpServletRequest request){
    boolean isAjaxRequest = false;
    if(!StringUtils.isBlank(request.getHeader("x-requested-with")) && request.getHeader("x-requested-with").equals("XMLHttpRequest")){
        isAjaxRequest = true;
    }
    return isAjaxRequest;
 }
}




package com.dalingjia.seckill.entity.response;

import lombok.Data;

import java.io.Serializable;

@Data
public class CheckAuthResponse implements Serializable {
  private static final long serialVersionUID = -3294145027267783959L;
  private String code;
  private String msg;
  private String uid;

 @Override
 public String toString() {
    return "CheckAuthResponse{" +
            "uid='" + uid + '\'' +
            "} " + super.toString();
 }
}
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容