前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JWT单点登录代码实现(Demo详解)

JWT单点登录代码实现(Demo详解)

作者头像
全栈程序员站长
发布2022-08-31 15:52:07
4680
发布2022-08-31 15:52:07
举报

大家好,又见面了,我是你们的朋友全栈君。

【辰兮要努力】:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行! 博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端、后台、数据库、项目案例等相关知识点总结,感谢你的阅读和关注,希望我的博客能帮助到更多的人,分享获取新知,大家一起进步! 吾等采石之人,应怀大教堂之心,愿你们奔赴在各自的热爱中…


文章目录


一、SSO概念

单点登录(Single Sign On),简称为 SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。

在这里插入图片描述
在这里插入图片描述

阿里系的淘宝和天猫,很明显地我们可以知道这是两个系统,但是你在使用的时候,登录了天猫,淘宝也会自动登录。

简述:当你成功登录后,系统会返回你一个令牌(凭证),你可以拿着这个令牌去访问所有相关的系统,只要你令牌即可访问,没有令牌就被拦截不能访问。(参考下图)

在这里插入图片描述
在这里插入图片描述

1、相比于单系统登录,sso需要一个独立的认证中心,只有认证中心能接受用户的用户名密码等安全信息,其他系统不提供登录入口,只接受认证中心的间接授权。

2、间接授权通过令牌实现,sso认证中心验证用户的用户名密码没问题,创建授权令牌,在接下来的跳转过程中,授权令牌作为参数发送给各个子系统,子系统拿到令牌,即得到了授权,可以借此创建局部会话,局部会话登录方式与单系统的登录方式相同。


二、JWT单点登录步骤

添加依赖

代码语言:javascript
复制
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.8.3</version>
</dependency>
<dependency>
    <groupId>io.jsonwebtoken</groupId>
    <artifactId>jjwt</artifactId>
    <version>0.9.1</version>
</dependency>

controller层的实现

代码语言:javascript
复制
    @RequestMapping("/login")
    public Map<String,String> login(String userName, String password){ 
   
        Map<String,String> map=new HashMap<>();
        try{ 
   
            String token = Jwts.builder().setSubject(userName) //主题,可以放用户的详细信息
                    .setIssuedAt(new Date()) //token创建时间
                    .setExpiration(new Date(System.currentTimeMillis() + 60000)) //token过期时间
                    .setId("userId") //用户ID
                    //.setClaims(hashMap) //配置角色信息
                    .signWith(SignatureAlgorithm.HS256, "WuHan") //加密方式和加密密码
                    .compact();
          // System.out.println("token:"+token);
            map.put("code","1");
            map.put("msg","success");
            map.put("token",token);
            map.put("user",userName);
        }catch (Exception e){ 
   
            map.put("code","0");
            map.put("msg","fail");
            e.printStackTrace();
        }
        return map;
    }

登录后可以把token打印出来自己看看,测试如下

代码语言:javascript
复制
token:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4YyIsImlhdCI6MTU5MTE1NDQwNiwiZXhwIjoxNTkxMTU0NDY2LCJqdGkiOiJ1c2VySWQifQ.c7gCDgIQ_I40dIWRxyG4yd1xaZQyWflnC7kX2Uoc9H8
代码语言:javascript
复制
token:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4YyIsImlhdCI6MTU5MTE1OTA1MSwiZXhwIjoxNTkxMTU5MTExLCJqdGkiOiJ1c2VySWQifQ.eUp0O2y83dc14f9NPUX049E9VxMpnkjuTcrheq2r9fM

token构成包含三个部分:

  • Header 头部
  • Payload 负载
  • Signature 签名
在这里插入图片描述
在这里插入图片描述

注意事项: ①根据需求设计过期时间(1秒 =1000 毫秒 ) ②因为我把时间设计到token里面了所以你可以测试每次产生的token不一样 ③设置userId那一栏-我目前是写死了 setId(“userId”) ,你可以根据需求设计不同的值进去


校验Token

代码语言:javascript
复制
try { 
   
    JwtParser parser = Jwts.parser();
    parser.setSigningKey("WuHan");//解析 要和上面“暗号”一样
    Jws<Claims> claimsJws = parser.parseClaimsJws(token);
    Claims body = claimsJws.getBody();
    String username = body.getSubject();
  // Object role = body.get("role");

    return true;
} catch (ExpiredJwtException e) { 
   
    e.printStackTrace();
} catch (UnsupportedJwtException e) { 
   
    e.printStackTrace();
} catch (MalformedJwtException e) { 
   
    e.printStackTrace();
} catch (SignatureException e) { 
   
    e.printStackTrace();
} catch (IllegalArgumentException e) { 
   
    e.printStackTrace();
}

setSigningKey() 与builder中签名方法signWith()对应,parser中的此方法拥有与signWith()方法相同的三种参数形式,用于设置JWT的签名key,用户后面对JWT进行解析。

isSigned() 校验JWT是否进行签名。方法很简单,以分隔符” . “,截取JWT第三段,即签名部分进行判断。


  • 案例前端代码实现登录模块如果成功登录,则存放token(也可以存放user根据需求看)
代码语言:javascript
复制
 <script type="text/javascript">
     
            $("#login").click(function () { 
   
                var name=$("#userName").val();
                var pwd=$("#password").val();
                $.post("http://localhost:8080/user/login",{ 
   userName:name,password:pwd},function(data) { 
   
                    console.log(data);
                    if(data.code=="1"){ 
   
                      /* document.cookie=data.token;*/
                        sessionStorage.setItem("token",data.token);
                        sessionStorage.setItem("user",data.user);
                        window.location.href="index.html";
                    }else{ 
   
                        window.location.href="login.html";
                    }
                },"json");
            });   
    </script>
  • 后续相关页面的安全校验,如果需要token才能访问的页面从存储的地方取出token,来进行校验,没有token说明没有登录则返回登录界面
代码语言:javascript
复制
    <script>
        var data = sessionStorage.getItem("token");
        if(data==null){ 
   
            window.location.href="login.html";
        }
    </script>
  • 补充:sessionStorage和localStorage

代码

含义

window.sessionStorage(会话存储)

暂时储存,浏览器关闭之后会清除

window.localStorage (本地存储)

本地储存,浏览器关闭之后依旧不会清除,只能人为删除

  • 平时储存的话建议使用sessionStorage;

开启Springboot拦截器引用上述校验token的代码

代码语言:javascript
复制
/** * 登录拦截 */
@Component
public class LoginInterceptor implements HandlerInterceptor { 
   

    @Override
    public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { 
   
        String token = request.getParameter("token");
        try { 
   
            JwtParser parser = Jwts.parser();
            parser.setSigningKey("WuHan");
            Jws<Claims> claimsJws = parser.parseClaimsJws(token);
            Claims body = claimsJws.getBody();
            String username = body.getSubject();
            Object role = body.get("role");
            return true;
        } catch (ExpiredJwtException e) { 
   
            e.printStackTrace();
        } catch (UnsupportedJwtException e) { 
   
            e.printStackTrace();
        } catch (MalformedJwtException e) { 
   
            e.printStackTrace();
        } catch (SignatureException e) { 
   
            e.printStackTrace();
        } catch (IllegalArgumentException e) { 
   
            e.printStackTrace();
        }
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { 
   

    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { 
   

    }
}

加载拦截器

代码语言:javascript
复制
@Configuration
public class AppConfig implements WebMvcConfigurer { 
   

    @Resource
    private LoginInterceptor loginInterceptor;

    /** * 添加拦截器 * @param registry */
    @Override
    public void addInterceptors(InterceptorRegistry registry) { 
   
        //.execudePathPatterns()//可以添加不拦截的地址
        registry.addInterceptor(loginInterceptor).addPathPatterns("/**");
    }
}

The best investment is to invest in yourself

在这里插入图片描述
在这里插入图片描述

2020.06.03 记录辰兮的第75篇博客

发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/143199.html原文链接:https://javaforall.cn

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022年5月2,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 文章目录
  • 一、SSO概念
  • 二、JWT单点登录步骤
相关产品与服务
访问管理
访问管理(Cloud Access Management,CAM)可以帮助您安全、便捷地管理对腾讯云服务和资源的访问。您可以使用CAM创建子用户、用户组和角色,并通过策略控制其访问范围。CAM支持用户和角色SSO能力,您可以根据具体管理场景针对性设置企业内用户和腾讯云的互通能力。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档