出处: https://www.cnblogs.com/zexin/p/10389541.html
我们平时自己开发项目,分布式的结构时,访问量不大,但是又不想搭建redis服务器,这时我觉得jwt不错.
个人理解,jwt就是类似于一把锁和钥匙,客户来租房(登录),我们需要给他进来(第一次登录)登记消息,配把钥匙给他(使用jwt生成一个token,存放在用的cookie中),
我们这边也需要配置一把我们需求的锁(jwt的生成token,解析token规则我们来写),接下来看下我最近运用jwt的小实例(该项目由springboot2.x搭建).
首先需要的maven工程pom.xml文件中添加依赖
io.jsonwebtoken jjwt 0.7.0
自定义一个拦截类,用户没有钥匙的都需要登录(jwt生成的token)
/** * 自定义登录拦截器 */public class LoginIntercepter implements HandlerInterceptor { private static final Gson gson = new Gson(); /** * 进入controller的拦截 * @param request * @param response * @param handler * @return * @throws Exception */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String token =""; //判断用户cookie中有无token Cookie[] ctoken = request.getCookies(); if(ctoken!=null){ for(Cookie ftoken: ctoken){ if(ftoken.getName().equals("token")){ token = ftoken.getValue(); } } } if (!token.isEmpty()){ //3.如果用户有token,则进行jwt解密 Claims claims = JWTUtils.checkToken(token); if (claims != null){ //4.不为空,则说明用户已登录,获取用户id,姓名,保存在request中的Attribute作用域中,这样controller就可以取到值 String signatureFile = (String) claims.get("signatureFile"); String email = (String) claims.get("email"); request.setAttribute("user_signatureFile",signatureFile); request.setAttribute("user_email",email); //5.放行 return true; } } //6.返回错误信息给前端 //sendMessage(response, JsonData.buildError("请登录")); //response.flushBuffer(); response.sendRedirect("sign_in.html"); return false; } /** * 发送错误信息给前端 */ public static void sendMessage(HttpServletResponse response, Object obj) throws IOException { response.setContentType("application/json;charset:utf-8"); PrintWriter writer = response.getWriter(); writer.print(gson.toJson(obj)); writer.close(); //需要刷新一下,怕有缓存 response.flushBuffer(); } }
springboot中需要配置一个配置类,注册我们的自定义配置类
/** *自定义拦截类的配置类 */@Configurationpublic class InterceptConfig implements WebMvcConfigurer { //注册一个我们登录的拦截类 @Override public void addInterceptors(InterceptorRegistry registry) { //我们需要排除登录,和注册的拦截(特别注意,我们还需要取消拦截静态资源的访问) String[] exclude = new String[]{"/sign_in.html","/sign_up.html","/static/**","/assets/**","/login","/user_register"}; //1.需要对我们自定义的拦截器进行注册 registry.addInterceptor(new LoginIntercepter()).addPathPatterns("/**").excludePathPatterns(exclude);//拦截路径 WebMvcConfigurer.super.addInterceptors(registry); } }
前面我们拦截类写好了,用户被拦截后会跳转到登录或者注册界面,这时,在我们的控制类中,我们需要根据表单提交的信息,生成相应的token,下面是控制类的重要代码,里面用到的JWTUtils下面会贴出来,方便大家复制
int save = userService.save(user);if (save == 1) { //return JsonData.buildSuccess(user,"注册成功"); //使用jwt来将用户信息生成token的字符串 String token = JWTUtils.geneToken(user); //将token保存到cookie中去,并且设置时间为半个钟 Cookie cookie = new Cookie("token",token); cookie.setMaxAge(60*30); response.addCookie(cookie); response.sendRedirect("/index"); //return JsonData.buildError("注册成功,即将跳转到首页!",0); } else { return new JsonData(-1,null,"注册失败,请重试"); }
用户登录后,cookie中会被保存我们jwt生成的token,我这里设置半个钟有效期,在上面的自定义拦截器中,用户访问页面,会先向用户拿取token,有token的话,会被解析出相应信息,并且直接跳入首页,无须登录.接下来下面是JWTUtils
public class JWTUtils { public static final String SUBJECT = "ouyan"; //编写发布者 public static final int EXPIRE = 1000*60*60*30; //设置过期时间,单位为毫秒,过期时间为半个钟 public static final String APPSECRET = "axin"; //设置密钥 /** * 使用jwt生成token */ public static String geneToken(User user){ //先判断是否为空,为空返回null if (user == null || user.getSignatureFile() == null || user.getEmail() == null ){ return null; } String token = Jwts.builder().setSubject(SUBJECT).claim("signatureFile",user.getSignatureFile()) .claim("email",user.getEmail()).setIssuedAt(new Date()).setExpiration(new Date(System.currentTimeMillis()+EXPIRE)) .signWith(SignatureAlgorithm.HS256,APPSECRET).compact(); return token; } /** * 校验密钥 */ public static Claims checkToken(String token) { try { final Claims claims = Jwts.parser().setSigningKey(APPSECRET) .parseClaimsJws(token).getBody(); return claims; } catch (Exception e) { e.printStackTrace(); System.out.println("出错啦"); } return null; } }