精华内容
下载资源
问答
  • token在客户端与服务器端的交互流程Token的优点和思考参考代码:核心代码使用参考,不是全部代码JWT token的组成头部(Header),格式如下:{“typ”: “JWT”,“alg”: “HS256”}由上可知,该token使用HS256加密算法...

    本文你能学到什么?

    token的组成

    token串的生成流程。

    token在客户端与服务器端的交互流程

    Token的优点和思考

    参考代码:核心代码使用参考,不是全部代码

    JWT token的组成

    头部(Header),格式如下:

    {

    “typ”: “JWT”,

    “alg”: “HS256”

    }

    由上可知,该token使用HS256加密算法,将头部使用Base64编码可得到如下个格式的字符串:

    eyJhbGciOiJIUzI1NiJ9

    有效载荷(Playload):

    {

    “iss”: “Online JWT Builder”,

    “iat”: 1416797419,

    “exp”: 1448333419,

    …….

    “userid”:10001

    }

    有效载荷中存放了token的签发者(iss)、签发时间(iat)、过期时间(exp)等以及一些我们需要写进token中的信息。有效载荷也使用Base64编码得到如下格式的字符串:

    eyJ1c2VyaWQiOjB9

    签名(Signature):

    将Header和Playload拼接生成一个字符串str=“eyJhbGciOiJIUzI1NiJ9.eyJ1c2VyaWQiOjB9”,使用HS256算法和我们提供的密钥(secret,服务器自己提供的一个字符串)对str进行加密生成最终的JWT,即我们需要的令牌(token),形如:str.”签名字符串”。

    token在服务与客户端的交互流程

    1:客户端通过用户名和密码登录

    2:服务器验证用户名和密码,若通过,生成token返回给客户端。

    3:客户端收到token后以后每次请求的时候都带上这个token,相当于一个令牌,表示我有权限访问了

    4:服务器接收(通常在拦截器中实现)到该token,然后验证该token的合法性(为什么能验证下面说)。若该token合法,则通过请求,若token不合法或者过期,返回请求失败。

    关于Token的思考

    服务如何判断这个token是否合法?

    由上面token的生成可知,token中的签名是由Header和有效载荷通过Base64编码生成再通过加密算法HS256和密钥最终生成签名,这个签名位于JWT的尾部,在服务器端同样对返回过来的JWT的前部分再进行一次签名生成,然后比较这次生成的签名与请求的JWT中的签名是否一致,若一致说明token合法。由于生成签名的密钥是服务器才知道的,所以别人难以伪造。

    token中能放敏感信息吗?

    不能,因为有效载荷是经过Base64编码生成的,并不是加密。所以不能存放敏感信息。

    Token的优点

    (1)相比于session,它无需保存在服务器,不占用服务器内存开销。

    (2)无状态、可拓展性强:比如有3台机器(A、B、C)组成服务器集群,若session存在机器A上,session只能保存在其中一台服务器,此时你便不能访问机器B、C,因为B、C上没有存放该Session,而使用token就能够验证用户请求合法性,并且我再加几台机器也没事,所以可拓展性好就是这个意思。

    (3)由(2)知,这样做可就支持了跨域访问。

    Java实例:JWT token使用

    部分代码来自互联网,找不到原作者了。。

    编写JWT(Java Web Token)操作类:JavaWebToken

    public class JavaWebToken {

    private static Logger log = LoggerFactory.getLogger(JavaWebToken.class);

    //该方法使用HS256算法和Secret:bankgl生成signKey

    private static Key getKeyInstance() {

    //We will sign our JavaWebToken with our ApiKey secret

    SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;

    byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary("bankgl");

    Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName());

    return signingKey;

    }

    //使用HS256签名算法和生成的signingKey最终的Token,claims中是有效载荷

    public static String createJavaWebToken(Map claims) {

    return Jwts.builder().setClaims(claims).signWith(SignatureAlgorithm.HS256, getKeyInstance()).compact();

    }

    //解析Token,同时也能验证Token,当验证失败返回null

    public static Map parserJavaWebToken(String jwt) {

    try {

    Map jwtClaims =

    Jwts.parser().setSigningKey(getKeyInstance()).parseClaimsJws(jwt).getBody();

    return jwtClaims;

    } catch (Exception e) {

    log.error("json web token verify failed");

    return null;

    }

    }

    }

    编写登录Conreoller,在服务器端给客户返回token.

    public LoginStatusMessage checkUserAndPassword(

    @RequestParam(value="username",required=true) String username,

    @RequestParam(value="password",required=true) String password,User user,HttpServletRequest request) throws Exception{

    User u = new User();

    //登录成功

    if((u = userService.checkUsernameAndPassword(user)) != null){

    Map m = new HashMap();

    m.put("userid", user.getUserid());

    String token = JavaWebToken.createJavaWebToken(m);

    System.out.println(token);

    LoginStatusMessage lsm = new LoginStatusMessage();

    lsm.setUser(u);

    lsm.setToken(token);

    return lsm;

    };

    //登录失败,返回Null

    return null;

    }

    在拦截器中对请求中的Token验证(部分代码,表示下意思):

    String token = request.getParameter("token");

    if(JavaWebToken.parserJavaWebToken(token) != null){

    //表示token合法

    return true;

    }else{

    //token不合法或者过期

    return false;

    }

    以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持脚本之家。

    展开全文
  • 退出登录时,如果不使JWT Token失效会产生如下2个问题问题1-未过期的token还是可以用要是用户在多个设备登录了,而且本地保存了token。当一个地方丢弃token,但是这个token要是没有过期,那之前token还是可以用的。...

    退出登录时,如果不使JWT Token失效会产生如下2个问题

    问题1-未过期的token还是可以用

    要是用户在多个设备登录了,而且本地保存了token。当一个地方丢弃token,但是这个token要是没有过期,那之前token还是可以用的。

    问题2-多个设备会出现死循环

    如果我把token存到数据库,当用户退出登录或者修改密码,更新token。当用户下次拿着之前的token来认证时,找到该用户数据库存的token,两个对比一下,如果一样就通过,否则让用户登录。有一个问题,如果这样做,要是有两设备,就死循环了。一个设备登录了,token就会变,导致另一个去登录,然后这个token又失效了,成死循环了。

    解决

    其实要完美地失效JWT是没办法做到的。

    "Actually, JWT serves a different purpose than a session and it is not possible to forcefully delete or invalidate an existing token."

    这篇文章写得比较简单易懂:https://medium.com/devgorilla...

    有以下几个方法可以做到失效 JWT token:

    将 token 存入 DB(如 Redis)中,失效则删除;但增加了一个每次校验时候都要先从 DB 中查询 token 是否存在的步骤,而且违背了 JWT 的无状态原则(这不就和 session 一样了么?)。

    维护一个 token 黑名单,失效则加入黑名单中。

    在 JWT 中增加一个版本号字段,失效则改变该版本号。

    在服务端设置加密的 key 时,为每个用户生成唯一的 key,失效则改变该 key。

    展开全文
  • Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).定义了一种简洁的,自包含的方法用于通信双方之间以JSON对象的形式安全的传递信息。因为数字签名的存在,这些信息...

    Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于 JSON 的开放标准((RFC 7519). 定义了一种简洁的,自包含的方法用于通信双方之间以 JSON 对象的形式安全的传递信息。因为数字签名的存在,这些信息是可信的,JWT 可以使用 HMAC 算法或者是 RSA 的公私秘钥对进行签名。

    JWT 请求流程

    这里还要注意:光理论是不够的。在此顺便送大家十套2020最新JAVA架构项目实战教程及大厂面试题库,进我扣裙 :七吧伞吧零而衣零伞 (数字的谐音)转换下可以找到了,还可以跟老架构师交流

    1. 用户使用账号和面发出 post 请求;

    2. 服务器使用私钥创建一个 jwt;

    3. 服务器返回这个 jwt 给浏览器;

    4. 浏览器将该 jwt 串在请求头中像服务器发送请求;

    5. 服务器验证该 jwt;

    6. 返回响应的资源给浏览器。

    JWT 的主要应用场景

    身份认证在这种场景下,一旦用户完成了登陆,在接下来的每个请求中包含 JWT,可以用来验证用户身份以及对路由,服务和资源的访问权限进行验证。由于它的开销非常小,可以轻松的在不同域名的系统中传递,所有目前在单点登录(SSO)中比较广泛的使用了该技术。 信息交换在通信的双方之间使用 JWT 对数据进行编码是一种非常安全的方式,由于它的信息是经过签名的,可以确保发送者发送的信息是没有经过伪造的。

    优点

    1. 简洁 (Compact): 可以通过 URL,POST 参数或者在 HTTP header 发送,因为数据量小,传输速度也很快

    2. 自包含 (Self-contained):负载中包含了所有用户所需要的信息,避免了多次查询数据库

    3. 因为 Token 是以 JSON 加密的形式保存在客户端的,所以 JWT 是跨语言的,原则上任何 web 形式都支持。

    4. 不需要在服务端保存会话信息,特别适用于分布式微服务。

    `

    JWT 的结构

    JWT 是由三段信息构成的,将这三段信息文本用. 连接一起就构成了 JWT 字符串。

    就像这样:

    eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ

    JWT 包含了三部分:

    Header 头部 (标题包含了令牌的元数据,并且包含签名和 / 或加密算法的类型)

    Payload 负载 (类似于飞机上承载的物品)

    Signature 签名 / 签证

    Header

    JWT 的头部承载两部分信息:token 类型和采用的加密算法。

    {

    "alg": "HS256",

    "typ": "JWT"

    }

    声明类型:这里是 jwt

    声明加密的算法:通常直接使用 HMAC SHA256

    加密算法是单向函数散列算法,常见的有 MD5、SHA、HAMC。

    MD5(message-digest algorithm 5) (信息 - 摘要算法)缩写,广泛用于加密和解密技术,常用于文件校验。校验?不管文件多大,经过 MD5 后都能生成唯一的 MD5 值

    SHA (Secure Hash Algorithm,安全散列算法),数字签名等密码学应用中重要的工具,安全性高于 MD5

    HMAC (Hash Message Authentication Code),散列消息鉴别码,基于密钥的 Hash 算法的认证协议。用公开函数和密钥产生一个固定长度的值作为认证标识,用这个标识鉴别消息的完整性。常用于接口签名验证

    Payload

    载荷就是存放有效信息的地方。

    有效信息包含三个部分

    1. 标准中注册的声明

    2. 公共的声明

    3. 私有的声明

    标准中注册的声明 (建议但不强制使用) :

    iss: jwt 签发者

    sub: 面向的用户 (jwt 所面向的用户)

    aud: 接收 jwt 的一方

    exp: 过期时间戳 (jwt 的过期时间,这个过期时间必须要大于签发时间)

    nbf: 定义在什么时间之前,该 jwt 都是不可用的.

    iat: jwt 的签发时间

    jti: jwt 的唯一身份标识,主要用来作为一次性 token, 从而回避重放攻击。

    公共的声明 :

    公共的声明可以添加任何的信息,一般添加用户的相关信息或其他业务需要的必要信息。但不建议添加敏感信息,因为该部分在客户端可解密.

    私有的声明 :

    私有声明是提供者和消费者所共同定义的声明,一般不建议存放敏感信息,因为 base64 是对称解密的,意味着该部分信息可以归类为明文信息。

    Signature

    jwt 的第三部分是一个签证信息,这个签证信息由三部分组成:

    header (base64 后的)

    payload (base64 后的)

    secret

    这个部分需要 base64 加密后的 header 和 base64 加密后的 payload 使用. 连接组成的字符串,然后通过 header 中声明的加密方式进行加盐 secret 组合加密,然后就构成了 jwt 的第三部分。

    密钥 secret 是保存在服务端的,服务端会根据这个密钥进行生成 token 和进行验证,所以需要保护好。

    下面来进行 SpringBoot 和 JWT 的集成

    引入 JWT 依赖,由于是基于 Java,所以需要的是 java-jwt

    com.auth0

    java-jwt

    3.4.0

    需要自定义一个注解

    需要登录并且具有角色才能才能进行操作的注解 LoginRequired

    @Target({ElementType.METHOD, ElementType.TYPE})

    @Retention(RetentionPolicy.RUNTIME)

    public @interface LoginRequired {

    // 是否进行校验

    boolean required() default true;

    // 默认管理员

    RoleEnum role() default RoleEnum.ADMIN;

    }

    @Target: 注解的作用目标

    @Target(ElementType.TYPE)—— 接口、类、枚举、注解

    @Target(ElementType.FIELD)—— 字段、枚举的常量

    @Target(ElementType.METHOD)—— 方法

    @Target(ElementType.PARAMETER)—— 方法参数

    @Target(ElementType.CONSTRUCTOR) —— 构造函数

    @Target(ElementType.LOCAL_VARIABLE)—— 局部变量

    @Target(ElementType.ANNOTATION_TYPE)—— 注解

    @Target(ElementType.PACKAGE)—— 包

    @Retention:注解的保留位置

    RetentionPolicy.SOURCE: 这种类型的 Annotations 只在源代码级别保留,编译时就会被忽略,在 class 字节码文件中不包含。

    RetentionPolicy.CLASS: 这种类型的 Annotations 编译时被保留,默认的保留策略,在 class 文件中存在,但 JVM 将会忽略,运行时无法获得。

    RetentionPolicy.RUNTIME: 这种类型的 Annotations 将被 JVM 保留,所以他们能在运行时被 JVM 或其他使用反射机制的代码所读取和使用。

    @Document:说明该注解将被包含在 javadoc 中

    @Inherited:说明子类可以继承父类中的该注解

    简单自定义一个实体类 User, 使用 lombok 简化实体类的编写

    @Data

    @Accessors(chain = true)

    public class AuthUserVO extends BaseVO {

    /**

    * 主键

    */

    private Long id;

    /**

    * 社交账户ID

    */

    private String socialId;

    /**

    * 用户名

    */

    private String name;

    /**

    * 密码

    */

    private String password;

    /**

    * 角色主键 1 普通用户 2 admin

    */

    private Long roleId;

    /**

    * 头像

    */

    private String avatar;

    private String token;

    }

    需要写 token 的生成方法

    /**

    * 生成Token

    * @param authUserVO

    * @return

    */

    public static String getToken(AuthUserVO authUserVO) {

    String sign = authUserVO.getPassword();

    return JWT.create().withExpiresAt(new Date(System.currentTimeMillis()+ Constants.EXPIRE_TIME)).withAudience(JsonUtil.toJsonString(authUserVO.setPassword(null)))

    .sign(Algorithm.HMAC256(sign));

    }

    Algorithm.HMAC256(): 使用 HS256 生成 token, 密钥则是用户的密码,唯一密钥的话可以保存在服务端。

    withAudience() 存入需要保存在 token 的信息,这里我把用户 ID 存入 token 中

    接下来需要写一个拦截器去获取 token 并验证 token

    实现一个拦截器就需要实现 HandlerInterceptor 接口

    HandlerInterceptor 接口主要定义了三个方法

    1.boolean preHandle ():

    预处理回调方法,实现处理器的预处理,第三个参数为响应的处理器,自定义 Controller, 返回值为 true 表示继续流程(如调用下一个拦截器或处理器)或者接着执行

    postHandle() 和 afterCompletion();false 表示流程中断,不会继续调用其他的拦截器或处理器,中断执行。

    2.void postHandle():

    后处理回调方法,实现处理器的后处理(DispatcherServlet 进行视图返回渲染之前进行调用),此时我们可以通过 modelAndView(模型和视图对象)对模型数据进行处理或对视图进行处理,modelAndView 也可能为 null。

    3.void afterCompletion():

    整个请求处理完毕回调方法,该方法也是需要当前对应的 Interceptor 的 preHandle() 的返回值为 true 时才会执行,也就是在 DispatcherServlet 渲染了对应的视图之后执行。用于进行资源清理。整个请求处理完毕回调方法。如性能监控中我们可以在此记录结束时间并输出消耗时间,还可以进行一些资源清理,类似于 try-catch-finally 中的 finally,但仅调用处理器执行链中

    主要流程:

    1. 从 http 请求头中取出 token,

    2. 判断是否映射到方法

    3. 检查是否有 passtoken 注释,有则跳过认证

    4. 检查有没有需要用户登录的注解,有则需要取出并验证

    5. 认证通过则可以访问,不通过会报相关错误信息

    配置拦截器

    在配置类上添加了注解 @Configuration,标明了该类是一个配置类并且会将该类作为一个 SpringBean 添加到 IOC 容器内

    @Configuration

    public class InterceptorConfig extends WebMvcConfigurerAdapter {

    @Override

    public void addInterceptors(InterceptorRegistry registry) {

    registry.addInterceptor(authenticationInterceptor())

    .addPathPatterns("/**"); // 拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录

    }

    @Bean

    public AuthenticationInterceptor authenticationInterceptor() {

    return new AuthenticationInterceptor();

    }

    }

    WebMvcConfigurerAdapter 该抽象类其实里面没有任何的方法实现,只是空实现了接口

    WebMvcConfigurer 内的全部方法,并没有给出任何的业务逻辑处理,这一点设计恰到好处的让我们不必去实现那些我们不用的方法,都交由 WebMvcConfigurerAdapter 抽象类空实现,如果我们需要针对具体的某一个方法做出逻辑处理,仅仅需要在

    WebMvcConfigurerAdapter 子类中 @Override 对应方法就可以了。

    注:

    在 SpringBoot2.0 及 Spring 5.0 中 WebMvcConfigurerAdapter 已被废弃

    网上有说改为继承 WebMvcConfigurationSupport,不过试了下,还是过期的

    解决方法:

    直接实现 WebMvcConfigurer (官方推荐)

    @Override

    public void addInterceptors(InterceptorRegistry registry) {

    // 可添加多个

    registry.addInterceptor(authenticationInterceptor).addPathPatterns("/**");

    }

    InterceptorRegistry 内的 addInterceptor 需要一个实现 HandlerInterceptor 接口的拦截器实例,addPathPatterns 方法用于设置拦截器的过滤路径规则。

    这里我拦截所有请求,通过判断是否有 @LoginRequired 注解 决定是否需要登录

    在数据访问接口中加入登录操作注解

    @LoginRequired

    @PutMapping("/admin/v1/update")

    public Result updateUser(@RequestBody AuthUserVO authUserVO) {

    return authUserService.updateUser(authUserVO);

    }

    注销登录

    网上很多案例都很少说怎么退出登录的,有点人说直接生成新的 token,我觉得还是后端控制比较好。这里我存储了每次生成的 token,用了一个定时器去扫描这里的过期 token,每次校验的时候都去数据库中看有没有,如果没有就报 token 验证失败。

    /**

    * 获取用户Session信息

    * @return

    */

    public static UserSessionVO getUserSessionInfo() {

    // 获取请求对象

    HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();

    // 获取请求头Token值

    String token = Optional.ofNullable(request.getHeader(Constants.AUTHENTICATION)).orElse(null);

    if (StringUtils.isBlank(token)) {

    return null;

    }

    // 获取 token 中的 user id

    AuthUser authUser = null;

    try {

    authUser = JsonUtil.parseObject(JWT.decode(token).getAudience().get(0), AuthUser.class);

    } catch (JWTDecodeException j) {

    ExceptionUtil.rollback("token解析失败", ErrorConstants.INVALID_TOKEN);

    }

    AuthUserDao userDao = BeanTool.getBean(AuthUserDao.class);

    AuthUser user = userDao.selectById(authUser.getId());

    if (user == null) {

    ExceptionUtil.rollback("用户不存在,请重新登录", ErrorConstants.LOGIN_ERROR);

    }

    // 验证 token

    JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getPassword())).build();

    try {

    jwtVerifier.verify(token);

    } catch (JWTVerificationException e) {

    ExceptionUtil.rollback("token验证失败", ErrorConstants.LOGIN_ERROR);

    }

    AuthTokenDao authTokenDao = BeanTool.getBean(AuthTokenDao.class);

    Integer count = authTokenDao.selectCount(new LambdaQueryWrapper().eq(AuthToken::getToken, token).eq(AuthToken::getUserId, user.getId()).ge(AuthToken::

    展开全文
  • JWT简介 :json Web Token(缩写JWT)是目前最流行的跨域认证解决方案session登录的认证方案是看,用户从客户端传递用户名和密码登录信息,服务端认证后将信息储存在session中,将session_id放入cookie中,以后访问...

    JWT简介 :

    json Web Token(缩写JWT)是目前最流行的跨域认证解决方案

    session登录的认证方案是看,用户从客户端传递用户名和密码登录信息,服务端认证后将信息储存在session中,将session_id放入cookie中,以后访问其他页面,服务器都会带着cookie,服务端会自动从cookie中获取session_id,在从session中获取认证信息。

    JWT的解决方案是,将认证信息返回个客户端,储存在客户端,下次访问其他页面,需要从客户端传递认证信息回服务器端。

    那么有人会问,将认证信息个客户端了,那么有坏人恶意修改,然后传递个服务器端怎么办呢,这个问题下面说JWT原理就会说到

    JWT原理

    JWT原理就是,服务器认证后,生成一个json格式的对象 ,发送个客户端,

    {

    "用户名": "admin",

    "角色": "超级管理员",

    "到期时间": "2019-07-13 00:00:00"

    }

    以后,客户端域服务器通信的时候,都要发回这个json对象,服务器完全靠这个对象认定用户身份,(但肯定不会像上面那样,那么简单的发送一个对象)这样的话,session中就没有数据了,后面更容易实现扩展

    JWT的数据结构

    JWT分为三个部分,header(头部) payload (负载) signature (签名)

    一个完整的JWT数据是这样的

    eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImp0aSI6IjNmMmc1N2E5MmFhIn0.

    eyJpYXQiOjE1NjI4MzM0MDgsImlzcyI6Imh0dHA6XC9cL3d3dy5weWcuY29tIiwiYXVkIjoiaHR0cDpcL1wvd3d3LnB5Zy5jb20iLCJuYmYiOjE1NjI4MzM0MDcsImV4cCI6MTU2MjkxOTgwOCwianRpIjoiM2YyZzU3YTkyYWEiLCJ1c2VyX2lkIjoxfQ.

    NFq1qQ-Z5c4pwit8ZkyWEwX6SBXmnHJcc6ZDgSD5nhU

    中间是有三个点的,分别就是 头部 负载 和签名 (点在每一行的最后)

    头部 是一个json对象 作用是描述JWT元数据,一般是这样的

    {

    "alg": "HS256", //表示签名的算法默认是 HMAC SHA256(写成 HS256)

    "typ": "JWT" //表示这个令牌(token)的类型(type),JWT 令牌统一写为JWT

    }

    最后,将上面的 JSON 对象使用 Base64URL 算法(详见后文)转成字符串。

    负载 也是一个 JSON 对象 ,用来存放实际需要传递的数据。JWT 规定了7个官方字段,供选用

    除了官方字段,你还可以在这个部分定义私有字段

    这个 JSON 对象也要使用 Base64URL 算法转成字符串(防止除了用户的人看见嘛)。

    注意:JWT 默认是不加密的,任何人都可以读到,所以不要把秘密信息放在这个部分。(虽然加密了,防止解密的坏人解密后修改在加密)

    签名 是对前两部分的签名(可以理解成在加密一份),防止数据篡改。

    首先,需要指定一个密钥(自己设置),这个密钥只有服务器才知道,不能泄露给用户。

    使用 Header 里面指定的签名算法(默认是 HMAC SHA256)产生签名

    如:HMACSHA256(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret) //使用Header 里面指定的签名算法 将头部和负载部用逗号拼接起来,在加上自己设置的秘钥

    那么签名就出来的。

    签名出来后,现在有了 头部的字符串,和负载的字符串 ,还有签名的,在将这三个字符串用. 拼接出来,就可以将这个拼接好的字符串,返回给客户端的

    JWT数据就返回得了客户端,需要注意的是,头部和负载部,是用base64URL转成字符串的,签名是用头部指定的算法转成字符串的 不用弄混掉

    JWT 的使用方式

    客户端,接受到了服务器返回的jwt,可以储存到cookie中,也可以储存在 localStorage。

    此后,客户端每次与服务器通信,都要带上这个 JWT。你可以把它放在 Cookie 里面自动发送,但是这样不能跨域,所以更好的做法是放在 HTTP 请求的头信息Authorization字段里面。

    一旦我们使用的JWT,JWT的类别人封装好的,会自动将生成的token放入响应头中去,然后再次去访问页面的时候会带着响应回来token去访问页面

    JWT在请求头中发送,如:会多了个请求头

    Authorization: Bearer

    然后,在服务器中,需要验证这个token,是否有效

    下面是实际应用在tp框架中

    当然需要通过composer安装JWT类

    composer require lcobucci/jwt 3.3 //安装jwt

    定义一个专门生成,和验证JWT的token

    namespace tools\jwt;

    use Lcobucci\JWT\Builder; //生成token类use Lcobucci\JWT\Parser;//解析tokenuse Lcobucci\JWT\Signer\Hmac\Sha256; //签名加密类use Lcobucci\JWT\ValidationData;//检测token

    class Token //在扩展中加入一个叫工具和jwt的文件夹,里面写入一个叫token的类{

    private static $_config = [ //生成token的基本参数 'audience' => 'http://www.mypyg.com',//接收人 'id' => 'zyt6b',//token的唯一www.pyg.com标识,这里只是一个简单示例 'sign' => 'zyt6b',//签名密钥 'issuer' => 'http://adminapi.pyg.com',//签发人 'expire' => 3600*24 //有效期 ];

    //生成token public static function getToken($user_id){//传来的用户id生成token

    //签名对象 $signer = new Sha256(); //获取签名对象数据 //获取当前时间戳 $time = time();

    //设置签发人、接收人、唯一标识、签发时间、立即生效、过期时间、用户id、签名 $token = (new Builder())->issuedBy(self::$_config['issuer'])//签发人 ->canOnlyBeUsedBy(self::$_config['audience'])//接收人 ->identifiedBy(self::$_config['id'], true)//标识id ->issuedAt($time)//签发时间 ->canOnlyBeUsedAfter($time-1) //生效时间 ->expiresAt($time + self::$_config['expire'])//过期时间 ->with('user_id', $user_id) //用户id加入token ->sign($signer, self::$_config['sign']) //签名秘钥 ->getToken(); //用上面信息生成token return (string)$token; //强制返回字符串token }

    //从请求信息中获取token令牌 public static function getRequestToken()

    {//在public里重写apache ,因为不处理,php中接收不到HTTP_AUTHORAZATION字段信息 //在public/.htaccess 中添加以下两行代码 //RewriteCond %{HTTP:Authorization} ^(.+)$ //RewriteRule .* - [E=HTTP_AUTHORIZATION:%{HTTP:Authorization}]

    if (empty($_SERVER['HTTP_AUTHORIZATION'])) { //判断有没有AUTHORIZATION字段的信息 return false; //server可以获得请求头信息 }

    //如果有AUTHORIZATION:就写入变量 $header = $_SERVER['HTTP_AUTHORIZATION'];

    $method = 'bearer';

    //去除token中可能存在的bearer标识 return trim(str_ireplace($method, '', $header));//忽略大小写,去除字符串首尾的空白字符 //将 $header 中的所有$method替换成''; //获取的时候去除多余的东西,只留一个token }

    //从token中获取用户id (包含token的校验) public static function getUserId($token = null)

    {

    $user_id = null;

    //判断$token是否是空,如果是空的话就从请求信息中获取token,否则就用自己 $token = empty($token)?self::getRequestToken():$token;

    //判断$token是否是空 return $token;die;

    if (!empty($token)) { //如果token不是空 //为了注销token 加以下if判断代码 $delete_token = cache('delete_token') ?: [];

    //从缓存中取出被标注被删除的token if(in_array($token, $delete_token)){//判断当前的token是否缓存中的删除中的token //token已被删除(注销) return $user_id;//如果在里面,返回用户id }

    $token = (new Parser())->parse((string) $token);//解析token $data = new ValidationData();//验证token的类 $data->setIssuer(self::$_config['issuer']);//验证的签发人 $data->setAudience(self::$_config['audience']);//验证的接收人 $data->setId(self::$_config['id']);//验证token标识

    if (!$token->validate($data)) { //如果验证失败 return $user_id; //返回用户id }

    $signer = new Sha256(); //验证签名秘钥的类 if (!$token->verify($signer, self::$_config['sign'])) {//验证签名秘钥 //签名验证失败 //token通过秘钥和加密的类的 看看能不能解析出来东西 return $user_id;

    }

    //从token中获取用户id $user_id = $token->getClaim('user_id');

    }

    return $user_id; //返回用户id 这里应该有值 }

    }

    展开全文
  • I am using jwt plugin and strategy in hapijs.I am able to create jwt token while login user and authenticate other API using the same token through 'jwt' strategy.I am setting the token in request.sta...
  • 业务场景在前后分离场景下,越来越多的项目使用token作为接口的安全机制,APP端或者WEB端(使用VUE、REACTJS等构建)使用token与后端接口交互,以达到安全的目的。本文结合stackover以及本身项目实践,试图总结出一个...
  • 1.JWT简介JSON Web Token (JWT)是一个开放标准(RFC 7519),它定义了一种紧凑的、自包含的方式,用于作为JSON对象在各方之间安全地传输信息。该信息可以被验证和信任,因为它是数字签名的。2 JSON Web Token的应用...
  • JWT(JSON Web Token)是目前最流行的认证方案之一。博客园、各种技术公众号隔三差五就会推一篇JWT相关的文章,真的多如牛毛。但我对JWT有点困惑,今天写出来跟大家探讨探讨,不要喷哈。JWT原理本文默认读者已经对...
  • 常见的鉴权方式有两种,一种是基于session,另一种是基于token方式的鉴权,我们来浅谈一下两种 鉴权方式的区别。两种鉴权方式对比session安全性:session是基于cookie进行用户识别的,cookie如果被截获,用户很容易...
  • 我最近也在做这个一个解决方案是oauth2 中把JwtTokenStore 改成RedisTokenStore ,然后登出的时候清redis另外还是借用的redis用户每次登录生成token,我还是在redis中把这个token存储登出的时候清除redis中存储的...
  • 什么是 JWT概念JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案。JWT 原理JWT 组成JWT 由三部分组成:Header,Payload,Signature 三个部分组成,并且最后由.拼接而成。HeaderHeader 部分是一个 JSON 对象,...
  • 什么是 JWT概念JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案。JWT 原理JWT 组成JWT 由三部分组成:Header,Payload,Signature 三个部分组成,并且最后由.拼接而成。HeaderHeader 部分是一个 JSON 对象,...
  • 什么是 JWT概念JSON Web Token(简称 JWT)是目前最流行的跨域认证解决方案。JWT 原理JWT 组成JWT 由三部分组成:Header,Payload,Signature 三个部分组成,并且最后由.拼接而成。HeaderHeader 部分是一个 JSON 对象,...
  • 在此文章中,我们将学习如何使用 JWT 身份验证在 Laravel 中构建 restful API 。JWT 代表 JSON Web Tokens 。我们还将使用 API 为用户产品创建功能齐全的 CRUD 应用。在使用跨平台应用程序时, API 是一个非常不错的...
  • JWT(JSON WEB TOKEN)的特点是无状态,通常用来作为验证登录以及鉴权,在这一方面,JWT体现出了他的优点。然而,如果使用JWT实现,用户主动注销、强制登出(禁止登陆)、忘记密码、修改密码,JWT续签等方面的需求,就会让...
  • 在前后端分离的项目中,登录策略也有不少,不过 JWT 算是目前比较流行的一种解决方案了,本文就和大家来分享一下如何将 Spring Security 和 JWT 结合在一起使用,进而实现前后端分离时的登录解决方案。1 无状态登录...
  • 为了支持注销,我的解决方案是在注销时将该token加入到服务器的redis黑名单中。 JWT与OAuth的区别 这两个概念总有人用混淆,所以一起介绍了。 OAuth2是一种授权框架,用在使用第三方账号登录的情况(比如使用weibo, ...
  • 流程1.使用微信小程序登录和获取用户信息Api接口2.把Api获取的用户资料和code发送给django后端3....后端通过JSON web token方式登录,把token和用户id传回小程序6.小程序将token和用户id保存在storag...
  • ddefewfewf:留着也没用啊Molita:不删留着干啥嘞就是 post session 和 delete session 嘛DavidNineRoc:jwt 好就好在不用存储数据库坏就坏在不用存储数据库正常情况下 jwt 不用处理登出, 如果非要做. 参考黑名单的...
  • 前言导读分析一下为什么要用OAuth2和JWT来做1. **单点登录(SSO)**方案单击登录方案是最常见的解决方案,但单点登录需要每个与用户交互的服务都必须与认证服务进行通信,这不但会造成重复,**也会产生大量琐碎的...
  • JWT token 如何实现注销或登出

    千次阅读 2020-03-12 18:46:19
    JWT存储在数据库中。您可以检查哪些令牌有效以及哪些令牌已被撤销,但这在我看来完全违背了使用JWT的目的。 从客户端删除令牌。这将阻止客户端进行经过身份验证的请求,但如果令牌仍然有效且其他人可以访问它,则...
  • JWT官网: [https://jwt.io/][https_jwt.io] JWT(Java版)的github地址:...Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).**定义了一种简洁...

空空如也

空空如也

1 2 3 4
收藏数 75
精华内容 30
关键字:

jwttoken注销