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

JWT单点登录代码实现(Demo详解)你好我是辰兮,很高兴你能来阅读,本篇给你介绍JWT单点登录的代码实现,后续会进一步分享源码的学习,献给初学者,共同成长,家一起进步。文章目录一、SSO概念二、JWT单点登录步骤一、SSO概念单点登录(SingleSignOn),简称为SSO,是目前比较流行的企业业务整合的解决方案之一。SSO的定义是在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统。阿里系的淘宝和天猫,很明显地我们可以知道这是两个系统,但是你在使用的时候,登录了天猫,淘宝也会自动登录。简述:当你成.

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

【辰兮要努力】:hello你好我是辰兮,很高兴你能来阅读,昵称是希望自己能不断精进,向着优秀程序员前行!

博客来源于项目以及编程中遇到的问题总结,偶尔会有读书分享,我会陆续更新Java前端、后台、数据库、项目案例等相关知识点总结,感谢你的阅读和关注,希望我的博客能帮助到更多的人,分享获取新知,大家一起进步!

吾等采石之人,应怀大教堂之心,愿你们奔赴在各自的热爱中…



一、SSO概念

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

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

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

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

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


二、JWT单点登录步骤

添加依赖

<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层的实现

    @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打印出来自己看看,测试如下

token:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4YyIsImlhdCI6MTU5MTE1NDQwNiwiZXhwIjoxNTkxMTU0NDY2LCJqdGkiOiJ1c2VySWQifQ.c7gCDgIQ_I40dIWRxyG4yd1xaZQyWflnC7kX2Uoc9H8
token:eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiJ4YyIsImlhdCI6MTU5MTE1OTA1MSwiZXhwIjoxNTkxMTU5MTExLCJqdGkiOiJ1c2VySWQifQ.eUp0O2y83dc14f9NPUX049E9VxMpnkjuTcrheq2r9fM

token构成包含三个部分:

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

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


校验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();
}

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

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


  • 案例前端代码实现登录模块如果成功登录,则存放token(也可以存放user根据需求看)
 <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说明没有登录则返回登录界面
    <script>
        var data = sessionStorage.getItem("token");
        if(data==null){ 
   
            window.location.href="login.html";
        }
    </script>
  • 补充:sessionStorage和localStorage
代码 含义
window.sessionStorage(会话存储) 暂时储存,浏览器关闭之后会清除
window.localStorage (本地存储) 本地储存,浏览器关闭之后依旧不会清除,只能人为删除
  • 平时储存的话建议使用sessionStorage;

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

/** * 登录拦截 */
@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 { 
   

    }
}

加载拦截器

@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篇博客

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

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

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • 使用outlook制作签名

    使用outlook制作签名使用outlook制作签名制作签名的几种方法直接在编辑器中编辑在Word中编辑好了复制过去直接在生成的文件上编辑直接用word新建htm格式编辑图片不清晰问题制作签名的几种方法你好,最近公司需要我制作公司签名,之前就想着不就是签名嘛,多简单的事。但是经过一系列的尝试之后,发现还真不容易。主要是因为outlook新建签名的编辑栏不支持直接使用html编辑。下面我介绍我尝试的几种方法直接在编辑…

    2022年10月16日
  • 3极管工作原理_通信终端工作原理

    3极管工作原理_通信终端工作原理一、很多初学者都会认为三极管是两个PN结的简单凑合(如图1)。这种想法是错误的,两个二极管的组合不能形成一个三极管。我们以NPN型三极管为例(见图2),两个PN结共用了一个P区——基区,基区做得极薄,只有几微米到几十微米,正是靠着它把两个PN结有机地结合成一个不可分割的整体,它们之间存在着相互联系和相互影响,使三极管完全不同于两个单独的PN结的特性。三极管在外加电压

  • Java队列实现

    Java队列实现一、队列简单介绍队列是一种常用的数据结构之一,与之前的栈类似,不过队列是“先进先出”。队列有队头(front)和队尾(rear),数据从队尾进入队列,从队头出队列,队头(front)指向队列的第一个数据,队尾(rear)指向队列中的最后一个数据。二、队列实现队列有很多种,这里只是介绍最基本的实现,采用链式存储,也就是链式队列,与之前的链表存储形式一样,通过结点对象描述一个数据,结点对象包含具体数

  • idea激活码2022【最新永久激活】

    (idea激活码2022)最近有小伙伴私信我,问我这边有没有免费的intellijIdea的激活码,然后我将全栈君台教程分享给他了。激活成功之后他一直表示感谢,哈哈~https://javaforall.cn/100143.htmlIntelliJ2021最新激活注册码,破解教程可免费永久激活,亲测有效,上面是详细链接哦~S32P…

  • ai的文件怎样将里面的文字转曲_PDF文件置入AI缺少字体

    ai的文件怎样将里面的文字转曲_PDF文件置入AI缺少字体AI文件中文字转曲是什么?怎么转曲?转曲百度百科

  • origin如何绘制双y轴柱状图_Graphpad柱状图双Y轴

    origin如何绘制双y轴柱状图_Graphpad柱状图双Y轴origin横坐标的标注如何修改成双行显示呢?shift+enter,可以换行思路:在两个图层上分别绘制两个柱状图,然后将两个图层合并。第一步:建立一个X列,四个Y列。其中,两列数据中间加上两个空列第二步:绘制第一个柱状图第三步:绘制第二个柱状图第四步:两图层合并点击合并按钮第五步:接下来就是坐标轴的显示基本上就完成了…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号