1.JWT是什么?

Json Web Token(JWT)是目前比较流行的跨域认证解决方案,是一种基于JSON的开发标准,由于数据是可以经过签名加密的,比较安全可靠,一般用于前端和服务器之间传递信息,也可以用在移动端和后台传递认证信息。

2.JWT的组成

让我们先来看看jwt的实际例子:

Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2wiOiJST0xFXzEiLCJpc3MiOiJTbmFpbENsaW1iIiwiaWF0IjoxNTk1OTkzMDQwLCJzdWIiOiIxNTAwMDAwMDAwMCIsImV4cCI6MTU5NjU5Nzg0MH0.Wxet2qPG1ajyG9CcQCN29gfKJzal0vCmQSXrwAgQwcI

我们可以看到,这个JWT包含3部分,是由“.”号分开的,Bearer是jwt中的一种前缀规范。

第一部分是Header:

eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9

第二部分是Payload:

eyJyb2wiOiJST0xFXzEiLCJpc3MiOiJTbmFpbENsaW1iIiwiaWF0IjoxNTk2MDAzODM4LCJzdWIiOiIxNTAwMDAwMDAwMCIsImV4cCI6MTU5NjYwODYzOH0

第三方部分是签名Signature:

MJmTSGBM9wRVOY40ORZuSGpT7FQNUcD2JlJxL0K0-YM

3.JWT的流程

先上图:

  1. 客户端登录接口输入用户名和密码提交到服务器;

  2. 服务器端校验用户名和密码,校验通过则创建一个JWT;

  3. 服务器端返回该JWT给客户端;

  4. 客户端每请求一次接口在Headers中带上返回的JWT;

  5. JWT自身的算法校验该JWT;

  6. 如果校验通过,操作DB,返回数据;反之返回状态码和错误信息。

4.SpringBoot集成JWT,代码实现

引入jwt的依赖库:

        <dependency>            <groupId>io.jsonwebtokengroupId>            <artifactId>jjwt-apiartifactId>            <version>0.10.7version>        dependency>        <dependency>            <groupId>io.jsonwebtokengroupId>            <artifactId>jjwt-implartifactId>            <version>0.10.7version>            <scope>runtimescope>        dependency>        <dependency>            <groupId>io.jsonwebtokengroupId>            <artifactId>jjwt-jacksonartifactId>            <version>0.10.7version>            <scope>runtimescope>        dependency>

JwtTokenUtils类:用于生成token

/** * @author kevincow */public class JwtTokenUtils {    /**     * 生成足够的安全随机密钥,以适合符合规范的签名     */    private static byte[] apiKeySecretBytes = Base64.getDecoder().decode(SecurityConstants.JWT_SECRET_KEY);    private static SecretKey secretKey = Keys.hmacShaKeyFor(apiKeySecretBytes);    public static String createToken(String username, List<String> roles) {        long expiration = SecurityConstants.EXPIRATION_REMEMBER;        String tokenPrefix = Jwts.builder()                .setHeaderParam("typ", SecurityConstants.TOKEN_TYPE)                .signWith(secretKey, SignatureAlgorithm.HS256)                .claim(SecurityConstants.ROLE_CLAIMS, String.join(",", roles))                .setIssuer("SnailClimb")                .setIssuedAt(new Date())                .setSubject(username)                .setExpiration(new Date(System.currentTimeMillis() + expiration * 1000))                .compact();        return SecurityConstants.TOKEN_PREFIX + tokenPrefix;    }}

接下来需要写一个过滤器去实现token的校验功能:

/** * 实现token的校验功能 * * 过滤器处理所有HTTP请求,并检查是否存在带有正确令牌的Authorization标头。例如,如果令牌未过期或签名密钥正确。 * * @author kevincow */public class JWTAuthorizationFilter extends BasicAuthenticationFilter {    private static final Logger logger = Logger.getLogger(JWTAuthorizationFilter.class.getName());    public JWTAuthorizationFilter(AuthenticationManager authenticationManager) {        super(authenticationManager);    }    @Override    protected void doFilterInternal(HttpServletRequest request,                                    HttpServletResponse response,                                    FilterChain chain) throws IOException, ServletException {        logger.info("token"+request.getHeader(SecurityConstants.TOKEN_HEADER));        String authorization = request.getHeader(SecurityConstants.TOKEN_HEADER);        // 如果请求头中没有token信息则直接放行了        if (authorization == null || !authorization.startsWith(SecurityConstants.TOKEN_PREFIX)) {            chain.doFilter(request, response);            return;        }        // 如果请求头中有token,则进行解析,并且设置授权信息        SecurityContextHolder.getContext().setAuthentication(getAuthentication(authorization));        super.doFilterInternal(request, response, chain);    }    /**     * 获取用户认证信息 Authentication     */    private UsernamePasswordAuthenticationToken getAuthentication(String authorization) {        String token = authorization.replace(SecurityConstants.TOKEN_PREFIX, "");        try {            String username = JwtTokenUtils.getUsernameByToken(token);            logger.info("checking username:" + username);            // 通过 token 获取用户具有的角色            List userRolesByToken = JwtTokenUtils.getUserRolesByToken(token);            if (!StringUtils.isEmpty(username)) {                return new UsernamePasswordAuthenticationToken(username, null, userRolesByToken);            }        } catch (SignatureException | ExpiredJwtException | MalformedJwtException | IllegalArgumentException exception) {            logger.warning("Request to parse JWT with invalid signature . Detail : " + exception.getMessage());        }        return null;    }}

最后写业务实现代码了(这里只展示控制层代码,业务代码就不一一赘述)

/**     * 微信端登录接口,在header中带上token     *     * @param userName     * @param passWord     * @return 是否登录成功     */    @ApiOperation(value = "用户登录成功之后,在header中带上token",            notes = "校验用户名密码,校验完成之后,在header中带上token", httpMethod = "GET")    @PostMapping("/whetherIsSysUser")    public SuccessResponse whetherRegister(@ApiParam("用户名") @RequestParam String userName,                                           @ApiParam("密码") @RequestParam String passWord,                                           HttpServletResponse response) {        try {            User user = userService.whetherRegister(userName, passWord);            if (StringUtils.isEmpty(user)) {                return SuccessResponse.of(false, "该用户未注册");            }            JwtUser jwtUser = new JwtUser(user);            List roles = jwtUser.getAuthorities()                    .stream()                    .map(GrantedAuthority::getAuthority)                    .collect(Collectors.toList());            String token = JwtTokenUtils.createToken(user.getPhone(), roles);            // Http Response Header 中返回 Token            response.setHeader(SecurityConstants.TOKEN_HEADER, token);        } catch (RuntimeException e) {            e.printStackTrace();            return SuccessResponse.of(false, "该用户未注册");        }        return SuccessResponse.of(true);    }

至此,代码实现部分差不多就完成了。接下来我们看下效果:

上图可以看到,登录接口用户名密码校验通过之后在headers中返回了Authorization。

然后当客户端请求其他接口并在请求头带上登录时返回的Authorization,就能正常响应了。

如果没有带上Authorization呢?那么会报一个错。

{    "timestamp": "2020-07-29 15:38:23",    "status": 401,    "error": "Unauthorized",    "message": "Full authentication is required to access this resource",    "path": "/wx/users/showNewVersion"}

以上就差不多是jwt的整个流程了。

5.总结

从特点中看优点:

  • JSON的通用性,决定了JWT是个跨语言的技术;

  • JWT token对于sessionid的方案来说,JWT可以携带任何我们想要用到的信息;

  • 安全性高,防止token伪造和篡改;

  • JWT token是自校验的形式,不需要任何其他请求和数据库操作,使我们系统管理会话更高效;

  • JWT不需要在服务端保存会话信息, 所以它易于应用的扩展

从特点中找缺点:

  • 一旦成功签发JWT token,无法手动将其过期;

  • 在token签发后的有效时间内,JWT无法做到及时获取最新数据,例如修改密码后无感知;

  • 存储空间、网络流量开销更大;

  • 为了安全,JWT需要使用https协议,以免token泄露

以上。

我是凯文cow,念念不忘,必有回响。

jwt获取token_JWT实现token认证相关推荐

  1. 接口使用jwt返回token_JWT实现token验证

    什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).定义了一种简洁的,自包含的方法用于通信双方之间以JSO ...

  2. tp6登录JWT获取token并认证

    1.命令创建jwt插件 composer require lcobucci/jwt 3.3 在模块中创建extend/tools/jwt/Token.php    <?phpnamespace ...

  3. Django+JWT实现Token认证

    对外提供API不用django rest framework(DRF)就是旁门左道吗? 基于Token的鉴权机制越来越多的用在了项目中,尤其是对于纯后端只对外提供API没有web页面的项目,例如我们通 ...

  4. JWT(Json web token)认证详解

    JWT(Json web token)认证详解 什么是JWT Json web token (JWT), 是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准((RFC 7519).该to ...

  5. jwt重放攻击_【干货分享】基于JWT的Token认证机制及安全问题

    一步一步教你基于JWT的Token认证机制实现,以及如何防范XSS攻击.Replay攻击和中间人攻击. 文章目录 一.几种常用的认证机制 1.1 HTTP Basic Auth HTTP Basic ...

  6. koa --- jwt实现最简单的Token认证

    HTML 有如下html: 先看代码后挑重点来说明: <!DOCTYPE html><head><script src="https://cdn.jsdeliv ...

  7. 程序员过关斩将--更加优雅的Token认证方式JWT

    点击上方"蓝字"带你去看小星星 菜菜,上次你讲的cookie和session认证方式,我这次面试果然遇到了 结果怎么样? 结果面试官问我还有没有更好的方式? 看来你又挂了 别说了, ...

  8. 接口使用jwt返回token_API接口JWT方式的Token认证(下),客户端(Android)的实现

    上篇文章已经介绍了 JWT 认证在 Laravel 框架服务器上的实现.这篇文章继续介绍 Android 客户端的实现.回顾下 JWT 认证的流程,客户端先提交账号密码进行登录,账号密码验证成功后,服 ...

  9. JWT实现Token认证

    为什么使用JWT? 随着技术的发展,分布式web应用的普及,通过session管理用户登录状态成本越来越高,因此慢慢发展成为token的方式做登录身份校验,然后通过token去取redis中的缓存的用 ...

最新文章

  1. hdoj 1269-迷宫城堡解题报告
  2. 学习笔记--asp.net母版页(转自msdn,仅为自己学习存储和有意读者使用)
  3. GCF(1)---How to modify PICS according to FGI bits UE reported
  4. 系统快捷方式java_java中这么创建界面快捷方式图标 代码
  5. html2canvas关于图片不能正常截取 1
  6. 记录贴:阿里云 ECS服务器CentOS系统 搭建 Hexo 博客详细教程
  7. ABB变频器配件,西门子变频器配件,施耐德变频器配件
  8. no.8 python 和 Linux (笔记)
  9. 如何进入进计算机组策略,如何进入组策略?
  10. 2022-06-28 工作记录--React-swiper + react-intersection-observer 实现图片在可视范围内时加上其对应动图
  11. Groovy框架Spock随0.6大发布
  12. 一句话题解(20170801~20170125)
  13. 完美解决无Internet但能正常上网的问题
  14. Java开发入门教程!java开发架构师职责
  15. java程序连接redis服务器
  16. vs code 语法_VS Code上的Java现在具有语法模式和SonarLint支持
  17. error: macro LIST_HEAD passed 2 arguments, but takes just 1
  18. JsonProperty.Access.READ_ONLY 导致查询字段为null
  19. 有N个灯放在一排,N个人进行操作,求灯泡最后的状态
  20. 5000字深度丨阿里巴巴用AI破局孕妇糖尿病

热门文章

  1. steelray project viewer
  2. 学大数据找IT十八掌
  3. 数据结构:点之间的最短距离--Floyd算法
  4. WinForm中使用WPF的控件
  5. CruiseControl.NET ----- mail 配置
  6. Linux 命令平时积累
  7. cognos10 安装部署
  8. [递归]一文看懂递归
  9. [爬虫][python][入门][网页源码][百度图片][豆瓣TOP250]
  10. mysql创建表格1warning_MySQL:创建、修改和删除表