个人学习系列-Spring-Boot整合JWT实现认证

6次阅读

共计 3202 个字符,预计需要花费 9 分钟才能阅读完成。

如何确保用户真实登陆?超时重新登陆?JWT 来了。

什么是 JWT

JWT(Json Web Token),是一种工具,格式为 XXXX.XXXX.XXXX 的字符串,JWT 以一种安全的方式在用户和服务器之间传递存放在 JWT 中的不敏感信息。

为什么要用 JWT

设想这样一个场景,在我们登录一个网站之后,再把网页或者浏览器关闭,下一次打开网页的时候可能显示的还是登录的状态,不需要再次进行登录操作,通过 JWT 就可以实现这样一个用户认证的功能。当然使用 Session 可以实现这个功能,但是使用 Session 的同时也会增加服务器的存储压力,而 JWT 是将存储的压力分布到各个客户端机器上,从而减轻服务器的压力。

JWT 操作流程图

Spring Boot 整合

1. pom.xml 配置依赖

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

2. 添加过滤器

这个类声明了一个 JWT 过滤器类,从 Http 请求中提取 JWT 的信息,并使用了 secretkey 这个密匙对 JWT 进行验证。

/**
 * 拦截器验证类
 * @author zhouzhaodong
 */
public class JwtFilter extends GenericFilterBean {

    /**
     * 秘钥
     */
    public static final String SECRET_KEY = "secretkey";

    @Override
    public void doFilter(final ServletRequest req, final ServletResponse res, final FilterChain chain)
            throws IOException, ServletException {final HttpServletRequest request = (HttpServletRequest) req;
        final HttpServletResponse response = (HttpServletResponse) res;

        // 从 request 中获取 authorization
        final String authHeader = request.getHeader("authorization");

        // 如果 Http 请求是 OPTIONS,那么只需返回状态代码 200 即可。String options = "OPTIONS";
        if (options.equals(request.getMethod())) {response.setStatus(HttpServletResponse.SC_OK);
        }
        else {

            // 判断 token 是否是用 Bearer 开头的
            String header = "Bearer";
            if (authHeader == null || !authHeader.startsWith(header)) {throw new ServletException("Missing or invalid Authorization header");
            }

            // 然后从授权处获取 JWT 令牌
            final String token = authHeader.substring(7);

            try {
                // 使用 JWT 解析器检查签名是否与 Key "secretkey" 有效。final Claims claims = Jwts.parser().setSigningKey(SECRET_KEY).parseClaimsJws(token).getBody();

                // 在请求标题中添加 claims
                request.setAttribute("claims", claims);
            } catch (final SignatureException e) {throw new ServletException("Invalid token");
            }

        }
        chain.doFilter(req, res);
    }
}

3. 拦截器

/**
 * 拦截器
 * @author zhouzhaodong
 */
@Configuration
public class JwtCfg {

    @Bean
    public FilterRegistrationBean<JwtFilter> jwtFilter() {final FilterRegistrationBean<JwtFilter> registrationBean = new FilterRegistrationBean<>();
        registrationBean.setFilter(new JwtFilter());
        // 对 /test/* 下的 url 进行拦截验证
        registrationBean.addUrlPatterns("/test/*");

        return registrationBean;
    }
}

4. 写一个 JWT 生成的方法类

/**
 * JWT 生成类
 * @author zhouzhaodong
 */
public class JwtUtils {

    public static final String SUBJECT = "admin";

    /**
     * 过期时间,毫秒,一天
     */
    public static final long EXPIRE = 1000 * 60 * 60 * 24;

    /**
     * 秘钥
     */
    public static final String SECRET_KEY = "secretkey";

    /**
     * 生成 jwt
     * @param userName
     * @param passWord
     * @return
     */
    public static String geneJsonWebToken(String userName, String passWord) {if (StringUtils.isEmpty(userName) || StringUtils.isEmpty(passWord)) {return "用户名或密码不能为空";}

        return Jwts.builder().setSubject(SUBJECT)
                .claim("userName", userName)
                .setIssuedAt(new Date())
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRE))
                .signWith(SignatureAlgorithm.HS256, SECRET_KEY).compact();}

}

5. 写测试方法

/**
 * 登陆
 * @author zhouzhaodong
 */
@RestController
public class TestController {@RequestMapping("/login")
    public String login(HttpServletResponse response, String userName, String passWord) {
        // 假装判断一下登陆是否成功
        if(userName == null || "".equals(userName) || passWord == null ||"".equals(passWord)){return "用户名或者密码不能为空";}
        String token = JwtUtils.geneJsonWebToken(userName, passWord);
        // 将 token 放在响应头
        response.setHeader("Authorization", token);
        return token;
    }

    @RequestMapping("/secure/check")
    public String check(){return "登陆成功";}

}

6. 启动验证

1. 运行 IDEA

2. 使用 postman 进行测试

首先需要访问 login 获取 token:

然后拿着该 token 去登录:

完成了,是不是比较简单!

源码地址

https://github.com/zhouzhaodo…

个人网站链接

http://www.zhouzhaodong.xyz

正文完
 0