java jwt 简单实现token验证用户登录

登录接口

@ApiOperation("登录接口")
    @PostMapping("/auth")
    public Result toLogin(@RequestBody InfoUser users){
        if (users.getUsername() == null || users.getPassword()==null) {
            return Result.error("用户名和密码不能为空");
        }
        InfoUser users1 = loginService.toLogin(users);
        if(users1==null){
            return Result.error("用户或密码错误");
        }else {
            //身份验证成功
            String token = TokenUtils.token(users.getUsername(), users.getPassword());
            if (token != null) {
                Map<String,Object> map = new HashMap<>();
                map.put("userInfo",users1);
                map.put("token",token);
                return Result.success(map);
            }
        }
        return Result.success(users1);
    }

拦截器,拦截除了登录请求以外的所有请求


import com.alibaba.fastjson.JSONObject;
import com.dfdt.util.PageUtils;
import com.dfdt.util.Result;
import com.dfdt.util.ResultEnum;
import com.dfdt.util.TokenUtils;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

@Component
public class TokenInterceptor implements HandlerInterceptor {

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
        response.setCharacterEncoding("UTF-8");
        //从前端传的request中获取token.需要与前端确认传的key是啥,我的是Authorization
        String token = request.getHeader("Authorization");
        if (null != token) {
        //判断token是否通过验证
            Result result= TokenUtils.verify(token);
            if (result.getCode().equals(200)) {
                return true;
            }else {
                response.getWriter().write(JSONObject.toJSONString(result));
                return false;
            }
        }
        Result<Object> error = Result.error(ResultEnum.TOKEN_ERROR);
        response.getWriter().write(JSONObject.toJSONString(error));
        return false;
    }
}

写好的拦截器需要通过这里添加注册才能生效

import com.dfdt.entity.ReadAppliationYml;
import com.dfdt.filter.TokenRefreshFilter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;


@Configuration
public class LoginAdapter implements WebMvcConfigurer {
    //解决跨域问题
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedHeaders("Content-Type","X-Requested-With","accept,Origin","Access-Control-Request-Method","Access-Control-Request-Headers","token")
                .allowedMethods("*")
                .allowedOrigins("*")
                //是否允许使用cookie
                .allowCredentials(true);
    }

    @Autowired
    private TokenInterceptor tokenInterceptor ;
    // 这个方法是用来配置静态资源的,比如html,js,css,等等
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        String mediaUploadPath = new ReadAppliationYml().getMediaUploadPath();
        String imageUploadPath = new ReadAppliationYml().getImageUploadPath();
        registry.addResourceHandler("/Media/**").addResourceLocations("file:/"+mediaUploadPath);
        registry.addResourceHandler("/Image/**").addResourceLocations("file:/"+imageUploadPath);
        WebMvcConfigurer.super.addResourceHandlers(registry);
    }
    
    // 这个方法用来注册拦截器,我们自己写好的拦截器需要通过这里添加注册才能生效
    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        System.out.println("进入拦截器");
        //需要放行的请求
        String[] pattrens = new String[]{"/**/auth","/**/*.html","/**/swagger-resources/**",
                "/**/webjars/**","/**/v2/**",
                "/**/swagger-ui.html"};
        //addPathPatterns是表明拦截哪些请求
        //excludePathPatterns是对哪些请求不做拦截
        registry.addInterceptor(tokenInterceptor).addPathPatterns("/**")
                .excludePathPatterns(pattrens);
    }


}

导包

<dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.2.0</version>
        </dependency>

token工具类

import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * @desc 使用token验证用户是否登录
 **/
public class TokenUtils {
    //设置过期时间
    private static final long EXPIRE_DATE = 60 * 60 * 1000 * 24; //一天
//    private static final long EXPIRE_DATE = 60 * 1000;//一分钟
    //token秘钥
    private static final String TOKEN_SECRET = "1234564654651313221321";//密钥自己设定一个

    /**
     * 生成签名,
     *
     * @param username
     * @param password
     * @return
     */
    public static String token(String username, String password) {

        String token = "";
        try {
            //过期时间
            Date date = new Date(System.currentTimeMillis() + EXPIRE_DATE);
            //秘钥及加密算法
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            //设置头部信息
            Map<String, Object> header = new HashMap<>();
            header.put("typ", "JWT");
            header.put("alg", "HS256");
            //携带username,password信息,生成签名
            token = JWT.create()
                    .withHeader(header)
                    .withClaim("username", username)
                    .withClaim("password", password).withExpiresAt(date)
                    .sign(algorithm);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
        return token;
    }

//    public static boolean verify(String token) {
//        /**
//         * @desc 验证token,通过返回true
//         * @params [token]需要校验的串
//         **/
//        try {
//            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
//            JWTVerifier verifier = JWT.require(algorithm).build();
//            DecodedJWT jwt = verifier.verify(token);
//            return true;
//        }catch (TokenExpiredException e1){
//            //token过期
//            e1.printStackTrace();
//            return false;
//        }catch (Exception e) {
//            //token没有验证通过
//            e.printStackTrace();
//            return false;
//        }
//    }


    public static Result verify(String token) {
        /**
         * @desc 验证token,通过返回true
         * @params [token]需要校验的串
         **/
        try {
            Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
            JWTVerifier verifier = JWT.require(algorithm).build();
            DecodedJWT jwt = verifier.verify(token);
            return Result.success(null);
        } catch (TokenExpiredException e1){
            //TokenExpiredException 该异常 为token 过期
//            e1.printStackTrace();
			//可以返回自己设定的token过期的code
            return Result.error(ResultEnum.TOKEN_PAST);
        }catch (Exception e) {
            //token 验证失败
//            e.printStackTrace();
            return Result.error(ResultEnum.TOKEN_ERROR);
        }
    }
    /**
     * 我们可以将一些常用的信息放入token中,比如用户登陆信息,方便我们的使用
     * 获得token中的信息无需secret解密也能获得
     */
    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("username").asString();
        } catch (Exception e) {
            return null;
        }
    }
    
}

接口返回实体


import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import org.apache.poi.ss.formula.functions.Count;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;

/**
 * 接口返回对象实体
 */
@Data
public final class Result<T> implements Serializable {

	private static final Logger logger = LoggerFactory.getLogger(Result.class);

    private static final long serialVersionUID = 1L;
    public static final String SUCCESSFUL_CODE = "000000";
    public static final String SUCCESSFUL_MESG = "处理成功";
    /**
     * 错误码
     */
    private Integer code = 0;

    /**
     * 错误信息
     */
    private String msg = null;

    private Integer count = 0;

    /**
     * 返回结果实体
     */
    private T data = null;

    public Result() {
    }

    public Result(Integer code, String msg, Integer count, T data) {
        this.code = code;
        this.msg = msg;
        this.count = count;
        this.data = data;
    }

    public Result(int code, String msg) {
        this.code = code;
        this.msg = msg;
    }

    public Result(ResultEnum resultEnum) {
        this.code = resultEnum.getCode();
        this.msg = resultEnum.getDesc();
    }

    public Result(ResultEnum resultEnum, T data) {
        this.code = resultEnum.getCode();
        this.msg = resultEnum.getDesc();
        this.data = data;
    }

    public static <T> Result<T> error(String msg) {
        logger.debug("返回错误:code={}, msg={}", ResultEnum.ERROR.getCode(), msg);
        return new Result<T>(ResultEnum.ERROR.getCode(), msg, null);
    }

    public static <T> Result<T> error(ResultEnum resultEnum) {
        logger.debug("返回错误:code={}, msg={}", resultEnum.getCode(), resultEnum.getDesc());
        return new Result<T>(resultEnum.getCode(), resultEnum.getDesc(), null);
    }

    public static <T> Result<T> error(int code, String msg) {
        logger.debug("返回错误:code={}, msg={}", code, msg);
        return new Result<T>(code, msg, null);
    }

    public static <T> Result<T> success(T data) {
        return new Result<T>(ResultEnum.SUCCESS.getCode(), "响应成功", 0,data);
    }

    public static <T> Result<T> success(T data, Integer count) {
        return new Result<T>(ResultEnum.SUCCESS.getCode(), "响应成功", count,data);
    }

    /**
     * 成功code=000000
     *
     * @return true/false
     */
    @JsonIgnore
    public boolean isSuccess() {
        return SUCCESSFUL_CODE.equals(this.code);
    }

    /**
     * 失败
     *
     * @return true/false
     */
    @JsonIgnore
    public boolean isFail() {
        return !isSuccess();
    }

    public Result(Integer code, String msg, T data) {
        this.code = code;
        this.msg = msg;
        this.data = data;
    }

    public static Logger getLogger() {
        return logger;
    }

    public static long getSerialVersionUID() {
        return serialVersionUID;
    }

    public static String getSuccessfulCode() {
        return SUCCESSFUL_CODE;
    }

    public static String getSuccessfulMesg() {
        return SUCCESSFUL_MESG;
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getMsg() {
        return msg;
    }

    public void setMsg(String msg) {
        this.msg = msg;
    }

    public T getData() {
        return data;
    }

    public void setData(T data) {
        this.data = data;
    }
}

枚举类 code和msg


public enum ResultEnum {
    // 成功
    SUCCESS(200, "成功"),

    // token异常
    TOKEN_PAST(301, "token过期"), TOKEN_ERROR(302, "token异常"),
    // 登录异常
    LOGIN_ERROR(303, "登录异常"), REMOTE_ERROR(304, "异地登录"),

    MENU_PAST(305, "菜单过期"), MENU_NO(306, "没此权限,请联系管理员!"),

    // 课程异常,4开头
    COURSE_SAVE_FAIL(403, "添加失败"), COURSE_UPDATE_FAIL(404, "更新失败"), COURSE_DELETE_FAIL(405, "删除失败"),
    //
    COLLECTION(406, "已收藏"), USER_ADVICE(406, "保存建议失败,不能重复提建议"), COURSE_AUDIT_FAIL(407, "审核失败"),

    // 用户异常,5开头
    LECTURER_REQUISITION_REGISTERED(501, "申请失败!该手机没注册,请先注册账号"), LECTURER_REQUISITION_WAIT(502, "申请失败!该账号已提交申请入驻成为讲师,待审核中,在7个工作日内会有相关人员与您联系确认"), LECTURER_REQUISITION_YET(503, "申请失败!该账号已成为讲师,请直接登录"),
    //
    USER_SAVE_FAIL(504, "添加失败"), USER_UPDATE_FAIL(505, "更新失败"), LECTURER_REQUISITION_FAIL(506, "申请失败!该账号已提交申请入驻成为讲师,审核不通过,请联系平台管理员"), USER_LECTURER_AUDIT(507, "审核失败"), USER_SEND_FAIL(508, "发送失败"),
    USER_DELETE_FAIL(509, "删除失败"),

    // 系統异常,6开头
    SYSTEM_SAVE_FAIL(601, "添加失败"), SYSTEM_UPDATE_FAIL(602, "更新失败"), SYSTEM_DELETE_FAIL(603, "删除失败"),

    // 错误
    ERROR(999, "错误");

    private Integer code;

    private String desc;

    ResultEnum(Integer code, String desc) {
        this.code = code;
        this.desc = desc;
    }

    ResultEnum() {
    }

    public Integer getCode() {
        return code;
    }

    public void setCode(Integer code) {
        this.code = code;
    }

    public String getDesc() {
        return desc;
    }

    public void setDesc(String desc) {
        this.desc = desc;
    }
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值