如何使用JWT来实现单点登陆功能

咱们平时本身开发项目,分布式的结构时,访问量不大,可是又不想搭建redis服务器,这时我以为jwt不错.html

我的理解,jwt就是相似于一把锁和钥匙,客户来租房(登陆),咱们须要给他进来(第一次登陆)登记消息,配把钥匙给他(使用jwt生成一个token,存放在用的cookie中),咱们这边也须要配置一把咱们需求的锁(jwt的生成token,解析token规则咱们来写),接下来看下我最近运用jwt的小实例(该项目由springboot2.x搭建).前端

首先须要的maven工程pom.xml文件中添加依赖web

<!-- JWT相关 -->
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.7.0</version>
        </dependency>

 

自定义一个拦截类,用户没有钥匙的都须要登陆(jwt生成的token)redis

/** * 自定义登陆拦截器 */
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中须要配置一个配置类,注册咱们的自定义配置类spring

/** *自定义拦截类的配置类 */ @Configuration public 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下面会贴出来,方便你们复制json

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; } }
相关文章
相关标签/搜索