SSM+JWT实现用户身份验证

记录SSM+JWT实现用户身份认证

1,导入Maven依赖
		<dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>3.4.0</version>
        </dependency>
2,JWTUtils工具类
public class JWTUtil {

    public static String createJWT(User user, long ttlMillis, Map<String, Object> claims) throws Exception {
        SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256; // 指定签名的时候使用的签名算法,也就是header那部分,jjwt已经将这部分内容封装好了。
        long nowMillis = System.currentTimeMillis();// 生成JWT的时间
        Date now = new Date(nowMillis);
        SecretKey key = generalKey();
        // 下面就是在为payload添加各种标准声明和私有声明了
        JwtBuilder builder = Jwts.builder() // 这里其实就是new一个JwtBuilder,设置jwt的body
                .setClaims(claims) // 如果有私有声明,一定要先设置这个自己创建的私有的声明,这个是给builder的claim赋值,一旦写在标准的声明赋值之后,就是覆盖了那些标准的声明的
                .setId(String.valueOf(user.getUserId())) // 这里是JWT的唯一标识,根据业务需要,这个可以设置为一个不重复的值,主要用来作为一次性token,从而回避重放攻击。
                .setIssuedAt(now) //  jwt的签发时间
                .setSubject(user.getUserName()) // 这里代表这个JWT的主体,可以是用户名,id,保证唯一就可以了
                .signWith(signatureAlgorithm, key);// 设置签名使用的签名算法和签名使用的秘钥
        if (ttlMillis >= 0) {
            long expMillis = nowMillis + ttlMillis;
            Date exp = new Date(expMillis);
            builder.setExpiration(exp); // 设置过期时间
        }
        return builder.compact(); // 生成jwt
    }

    /**
     * 解密jwt
     */
    public static Claims parseJWT(String jwt) throws Exception {
        SecretKey key = generalKey(); // 签名秘钥,和生成的签名的秘钥一模一样
        Claims claims = Jwts.parser() // 得到DefaultJwtParser
                .setSigningKey(key) // 设置签名的秘钥
                .parseClaimsJws(jwt).getBody();// 设置需要解析的jwt
        return claims;
    }

    /**
     * 由字符串生成加密key
     */
    public static SecretKey generalKey() {
        byte[] encodedKey = Base64.decodeBase64("123");// 本地的密码解码,这里自定义
        SecretKey key = new SecretKeySpec(encodedKey, 0, encodedKey.length, "AES");// 根据给定的字节数组使用AES加密算法构造一个密钥,使用
        return key;
    }

    /**
     * 将jwt过期(拉入黑名单)
     *
     * @param jwt
     */
    public static void expireJWT(String jwt) {
        Jedis jedis = JedisUtil.getJedis();
        if (jedis.exists(jwt)) {
            jedis.del(jwt);
        }
        jedis.set(jwt, jwt, "NX", "PX", 86400000);//默认时间一天
    }

    /**
     * 判断JWT是否在黑名单里
     *
     * @param jwt
     * @return
     */
    public static boolean isExpireJWT(String jwt) {
        Jedis jedis = JedisUtil.getJedis();
        return jedis.exists(jwt);
    }

相关的JedisUtil工具类

public final class JedisUtil {
    private static JedisPool jedisPool;

    static {
        //读取配置文件
        InputStream is = JedisPool.class.getClassLoader().getResourceAsStream("jedis.properties");
        //创建Properties对象
        Properties pro = new Properties();
        //关联文件
        try {
            pro.load(is);
        } catch (IOException e) {
            e.printStackTrace();
            jedisPool = null;
        }
        //获取数据,设置到JedisPoolConfig中
        JedisPoolConfig config = new JedisPoolConfig();
        config.setMaxTotal(Integer.parseInt(pro.getProperty("maxTotal")));
        config.setMaxIdle(Integer.parseInt(pro.getProperty("maxIdle")));

        //初始化JedisPool
        jedisPool = new JedisPool(config, pro.getProperty("host"), Integer.parseInt(pro.getProperty("port")));

    }


    /**
     * 获取连接方法
     */
    public static Jedis getJedis() {
        if (jedisPool != null)
            return jedisPool.getResource();
        return null;
    }

    /**
     * 关闭Jedis
     */
    public static void close(Jedis jedis) {
        if (jedis != null) {
            jedis.close();
        }
    }
3,使用
	Map payload = new HashMap();
	payload.put("user", user);
	JWTUtil.createJWT(user, 86400000, payload);

拉黑示例

	String token = JWTUtil.createJWT(user, 86400000, payload);;
	JWTUtil.expireJWT(token);
4,实现用户身份认证
4.1,定义认证注解
	//用于判断该控制器是否需要用户登录权限
	@Target({ElementType.METHOD})
	@Retention(RetentionPolicy.RUNTIME)
	public @interface UserLoginAnno {
   		boolean value() default true;
	}
4.2,定义拦截器

4.2.1,配置拦截器

	<mvc:interceptors>
        <mvc:interceptor>
            <mvc:mapping path="/**" />
            <bean class="cn.interceptor.MyInterceptor"></bean>
        </mvc:interceptor>
    </mvc:interceptors>

4.2.2,编写控制器代码

public class	MyInterceptor implements HandlerInterceptor {
    @Autowired
    private UserService userService;//userService中有根据用户id获取用户信息的方法,就不拿出来了

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object object) throws Exception {

        if (!(object instanceof HandlerMethod)) {
            return true;
        }

        HandlerMethod handlerMethod = (HandlerMethod) object;
        Method method = handlerMethod.getMethod();
        if (method.isAnnotationPresent(UserLoginAnno.class)) {
            UserLoginAnno userLoginAnno = method.getAnnotation(UserLoginAnno.class);
            if (userLoginAnno.value()) {
                String token = request.getHeader("token");
                // 执行认证
                if (token == null) {
                    throw new RuntimeException("无token,请重新登录!");
                }

                //检查token是否在黑名单中
                if (JWTUtil.isExpireJWT(token)) {
                    //在黑名单中
                    throw new RuntimeException("请重新登录");
                }

                User user;
                try {
                    user = ObjectMapperUtil.readValue(ObjectMapperUtil.writeValueAsString(JWTUtil.parseJWT(token).get("user")), User.class);
                } catch (JWTDecodeException j) {
                    throw new RuntimeException("访问异常!");
                }
                user = userService.findUserById(user.getUserId());
                if (user == null) {
                    throw new RuntimeException("用户不存在,请重新登录!");
                }
                request.setAttribute("user", user);//验证过得user对象存入request中,方便使用
                return true;
            }
        }
        return true;
    }
}
4.3,使用
	/**
     * 获取用户信息接口
     *
     * @return
     */
    @RequestMapping("findUserInfo")
    @UserLoginAnno
    @ResponseBody
    public Result findUserInfo(HttpServletRequest request) {
        return Result.createBySuccess("获取成功", "userInfo", request.getAttribute("user"));
    }
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值