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

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

什么是JWT

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

为什么要用JWT

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

JWT操作流程图

个人学习系列 - Spring Boot整合JWT实现认证_第1张图片

Spring Boot整合

1. pom.xml配置依赖


    io.jsonwebtoken
    jjwt
    0.9.0

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() {
        final FilterRegistrationBean 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

个人学习系列 - Spring Boot整合JWT实现认证_第2张图片

2. 使用postman进行测试

首先需要访问login获取token:
个人学习系列 - Spring Boot整合JWT实现认证_第3张图片

然后拿着该token去登录:
个人学习系列 - Spring Boot整合JWT实现认证_第4张图片

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

源码地址

https://github.com/zhouzhaodo...

个人网站链接

http://www.zhouzhaodong.xyz

你可能感兴趣的:(java,springboot,jwt)