美文网首页javaWeb学习Java Web架构设计springboot
重拾后端之Spring Boot(四):使用JWT和Spring

重拾后端之Spring Boot(四):使用JWT和Spring

作者: 接灰的电子产品 | 来源:发表于2017-03-10 20:39 被阅读65343次

重拾后端之Spring Boot(一):REST API的搭建可以这样简单
重拾后端之Spring Boot(二):MongoDb的无缝集成
重拾后端之Spring Boot(三):找回熟悉的Controller,Service
重拾后端之Spring Boot(四):使用 JWT 和 Spring Security 保护 REST API
重拾后端之Spring Boot(五):跨域、自定义查询及分页
重拾后端之Spring Boot(六):热加载、容器和多项目

通常情况下,把API直接暴露出去是风险很大的,不说别的,直接被机器攻击就喝一壶的。那么一般来说,对API要划分出一定的权限级别,然后做一个用户的鉴权,依据鉴权结果给予用户开放对应的API。目前,比较主流的方案有几种:

  1. 用户名和密码鉴权,使用Session保存用户鉴权结果。
  2. 使用OAuth进行鉴权(其实OAuth也是一种基于Token的鉴权,只是没有规定Token的生成方式)
  3. 自行采用Token进行鉴权

第一种就不介绍了,由于依赖Session来维护状态,也不太适合移动时代,新的项目就不要采用了。第二种OAuth的方案和JWT都是基于Token的,但OAuth其实对于不做开放平台的公司有些过于复杂。我们主要介绍第三种:JWT。

什么是JWT?

JWT是 Json Web Token 的缩写。它是基于 RFC 7519 标准定义的一种可以安全传输的 小巧自包含 的JSON对象。由于数据是使用数字签名的,所以是可信任的和安全的。JWT可以使用HMAC算法对secret进行加密或者使用RSA的公钥私钥对来进行签名。

JWT的工作流程

下面是一个JWT的工作流程图。模拟一下实际的流程是这样的(假设受保护的API在/protected中)

  1. 用户导航到登录页,输入用户名、密码,进行登录
  2. 服务器验证登录鉴权,如果改用户合法,根据用户的信息和服务器的规则生成JWT Token
  3. 服务器将该token以json形式返回(不一定要json形式,这里说的是一种常见的做法)
  4. 用户得到token,存在localStorage、cookie或其它数据存储形式中。
  5. 以后用户请求/protected中的API时,在请求的header中加入 Authorization: Bearer xxxx(token)。此处注意token之前有一个7字符长度的 Bearer
  6. 服务器端对此token进行检验,如果合法就解析其中内容,根据其拥有的权限和自己的业务逻辑给出对应的响应结果。
  7. 用户取得结果
Angular从零到一

相关文章

网友评论

  • ac43d4bebed3:第三部分签名信息不是可以防止篡改吗
  • 删我丶:添加PreAuthorize @PreAuthorize("hasAnyRole('ROLE_ADMIN')")
    后报403{
    "timestamp": 1533267174614,
    "status": 403,
    "error": "Forbidden",
    "message": "Access Denied",
    "path": "/user-system/users"
    }
    调试拥有ADMIN角色。。。。
    请问大佬这是什么原因
    阿懒土灵:hasAnyRole("ADMIN"),该这样写,将前面的”ROLE_“去掉
  • 9dd7169f9b6b:你好,请问在jwtTokenUtil中 的validateToken, 我之看到了比较用户名和 token中携带的用户名是否匹配, 并没有看到验证第三段签名的逻辑代码. 可是我尝试过各种测试, 均无法破解该验证. 所以请问 验证签名的代码到底存在哪里
  • 旺叔叔:JwtTokenUtil 这个类是包里的吗还是自己写的 希望能看到代码
    旺叔叔:@akirayimi 时间过去一阵 已经找到解决方案 但是看到回复依然很激动 感谢博主
    akirayimi:https://github.com/szerhusenBC/jwt-spring-security-demo/blob/master/src/main/java/org/zerhusen/security/JwtTokenUtil.java
  • 4896d2e4a35d:看到您是基于角色层面的控制,如果是通过角色下的资源做为方法级别的控制呢?
  • wdom:很详细的资料,照着写了一些接口,能用rest client工具测试吗,比如
    Wisdom RESTClient
    https://github.com/Wisdom-Projects/rest-client
  • d919d7b0eb7e:刚接触spring security,跑了您的例子,认证的内部逻辑都没有问题,但是发现验证token的filter每次请求都会执行两次,请教一下是什么原因?
    9dd7169f9b6b:@小花_d67a 我也想知道!
    ba940dd7721f:@小花_d67a 什么原因导致的呢?我没搞明白,麻烦说一下吧,多谢了。
    d919d7b0eb7e:额,已找到原因。。。请忽视
  • Dragon_e6e8:咋没有pom文件呀
  • c794f7e70034:指教一下,在springcloud环境下,rest如何完成认证,使用token调用微服务服务
  • c6240cf4912d:请问。 用这个 怎么能多途径登录。 即能用用户名密码 也能支持微信第三方登录之类的。谢谢
    心尘宁静:哥们 找到方案了么, 我也想知道jwt 怎么支持多途径登陆
  • f125956e07fc:如果做app端的保持登陆状态,是否是在login方法中先判断token是否存在,存在,就把第一次登陆一健对值的redis储存取出来返回过去。
  • liunewshine:“我们足够相信签名token的secret的机制足够好,这种情况下,我们可以不用再查询数据库,而直接采用token中的数据”
    这个应该做不到,权限信息必须查询数据库的吧?不可能都放入jwt中,会使jwt长度过长而且如果更改了权限,token是无法更新的
    liunewshine:如果必须查询数据库的话,由于没有session做缓存,会导致每一次请求都需要查询数据库,很耗费性能,怎么解呢?
  • zw900808:大神已经解决了,问题是出在我在JwtUser.java的时候,应该是:
    @JsonIgnore
    @Override
    public String getPassword() {
    return password;
    }

    @Override
    public String getUsername() {
    return username;
    }
    可是我写成了:
    @JsonIgnore
    @Override
    public String getPassword() {
    return null;
    }

    @Override
    public String getUsername() {
    return null;
    }
  • df2e9104e2df:请教一下,假如我想实现类似于微信公众号里的会员中心功能(用户点击公众号的菜单可以进入个人中心)这种没有用户名跟密码的认证应该怎么做?我该怎么保护我后台的api接口访问权限?
  • krmao:```
    @service
    class JWTTokenUtils {
    val logger: Logger = LogManager.getLogger(JWTTokenUtils::class.java.name)

    @VALUE("\${jwt.secret}")
    private var secret: String? = null

    @VALUE("\${jwt.access_token.expiration}")
    private var access_token_expiration: Long? = null

    @VALUE("\${jwt.refresh_token.expiration}")
    private var refresh_token_expiration: Long? = null
    ```
    为什么拿不到 application.yml 里面的值呢?

    ···
    jwt:
    secret: "xxx"
    tokenHead: "Bearer "
    header: "Authorization"
    access_token:
    expiration: 60
    refresh_token:
    expiration: 60
    ···
  • zw900808:为什么我登录获取token报401:Unauthorized
    zw900808:{
    "timestamp": 1511784602501,
    "status": 401,
    "error": "Unauthorized",
    "exception": "org.springframework.security.authentication.InternalAuthenticationServiceException",
    "message": "Unauthorized",
    "path": "/auth"
    }
    zw900808:路径是:/auth
  • QuY:http://localhost:8088/auth/register在postman上注册,后端报这个错org.springframework.security.access.AccessDeniedException: Access is denied
    at org.springframework.security.access.vote.AffirmativeBased.decide(AffirmativeBased.java:84) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]
    at org.springframework.security.access.intercept.AbstractSecurityInterceptor.beforeInvocation(AbstractSecurityInterceptor.java:233) ~[spring-security-core-4.2.3.RELEASE.jar:4.2.3.RELEASE]......
    是为什么啊?步骤都是按照您上面一步步做的。
  • 紫玄:我的auth路径始终无法访问,被拒绝.........可是我明明已经设置允许了啊
    紫玄:@mystic_cc ![图片](https://i.loli.net/2017/11/02/59fa8f9799586.png)
    紫玄:@mystic_cc 始终被拒绝
    紫玄:auth/register可以注册成功,可是直接auth去登录,就不可以,Access Denied,不晓得哪里出问题了
  • Hugh1029:找了一下午关于这个的详细解读,作者解读的很详细,还没看完,以后遇到什么问题希望可以请教一下作者~
  • bagonfan:写的很好 问一下 这个 怎么跟zuul 网关结合起来呢?
  • bc8cdd63ae38:如果是跨域情况下,默认会先请求服务器是否允许跨域,然后再发送真实的请求,这种情况下的拦截机制应该怎么实现呢?有朋友可以给予帮助吗?
    yongaliang:@xlboombaby https://github.com/kioyong/yong-security 参考 CorsFilter.java 和 Oauth2ServerConfig.java 里面的 WebSecurityConfig (+ @Order(-1))
    夏不见秋:@yongaliang 我需要例子:smiley:
    yongaliang:如果你还没解决话我可以给予你帮助,我也是花了很久时间解决这个问题。需要的话我可以给你例子
  • Harlan1994:感觉很棒,但是有一个问题想问下,我很奇怪的是,为什么有了User还要另外建立一个JwtUser呢,为什么不在User上作文章呢?
    9dd7169f9b6b:如果在jwtUser 上直接做文章的话, 一些属性会暴露在json中 比如password。 (如果你json ignore的话,则登陆的时候就收不到json里面的密码了) 所以分离是为了更好的暴露必要的json 数据,隐藏安全数据
  • 707e827c5153:非常 :+1: 的文章,先前了解过JWS/JWT以及HMAC之后觉得已经能够上手融合Spring了。
    有一个小疑问就是token的refresh是在什么场景下使用的。
  • c01665d14f48:请问下,如何设置token的失效时间,我使用postman重新的去调用/auth,每次返回的token也是不一样的,但是在请求的Authorization中还是原先的token,仍然可以访问,请问有啥解决的办法吗?
    c01665d14f48:@孫琦 谢谢。
    cd9d1df464cf:他写的只是一个de'mo 校验token有效知识写了一个简便的方法 你可以生成token的时候存到redis里 userid作为key
  • 358408ceda43:请问,如果我是用手机号来做登录,是不是在JwtUser的getUsername方法中返回mobile即可?
  • c01665d14f48:使用Postman进行注册的时候出现这个,我发送的请求是:
    http://localhost:8999/auth/register?username=wangyi&password=1517&email=1517@QQ.com
    {
    "timestamp": 1504100483086,
    "status": 400,
    "error": "Bad Request",
    "exception": "org.springframework.http.converter.HttpMessageNotReadableException",
    "message": "Required request body is missing: public com.appo.attendancesys.apiauth.user.User com.appo.attendancesys.apiauth.auth.AuthController.register(com.appo.attendancesys.apiauth.user.User) throws org.springframework.security.core.AuthenticationException",
    "path": "/auth/register"
    }
    c01665d14f48:可以加个qq问下吗?有很多细节摸不着头脑
    接灰的电子产品:童鞋,请用 post 提交
  • 冷冷zz:如果客户端的Token 过期,是不是要自动刷新? JwtAuthenticationTokenFilter 没有这块逻辑呀 大佬:relaxed:
  • 92610587a15e:大神在吗?按照你的例子,我把功能弄到我项目里面,项目启动就会出下面的错误,初始化失败,是不是少引了什么包
    Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'org.springframework.security.authentication.AuthenticationManager' available:

    @Autowired
    public AuthServiceImpl(
    AuthenticationManager authenticationManager,
    UserDetailsService userDetailsService,
    JwtTokenUtil jwtTokenUtil,
    UserRepository userRepository) {
    this.authenticationManager = authenticationManager;
    this.userDetailsService = userDetailsService;
    this.jwtTokenUtil = jwtTokenUtil;
    this.userRepository = userRepository;
    }

  • Ray916:大神您好,我的配置文件用的是.properties格式,请问application.yml中关于jwt的几个可以直接在application.properties中改写吗?谢谢
    Ray916:@接灰的电子产品 收到大神回复真是激动,我现在改成yml格式了哈哈,但是我遇到一个问题,就是用已经注册的用户名和密码去申请token的时候显示如下:
    {
    "timestamp": 1502240238418,
    "status": 401,
    "error": "Unauthorized",
    "exception": "org.springframework.security.authentication.InternalAuthenticationServiceException",
    "message": "Unauthorized",
    "path": "/auth/"
    }
    感觉像是 在
    final Authentication authentication = authenticationManager.authenticate(upToken);
    SecurityContextHolder.getContext().setAuthentication(authentication);
    这一步出了问题,但是没有报任何错误,请大神指教,感谢!
    _yoyo_:server.port=8089
    spring.jackson.serialization.INDENT_OUTPUT=true
    spring.data.mongodb.host=localhost
    spring.data.mongodb.port=27017
    spring.data.mongodb.database=springboot

    # jwt
    jwt.header=Authorization
    jwt.secret=mySecret
    jwt.expiration=604800
    jwt.tokenHead=Bearer
    jwt.route.authentication.path=auth
    jwt.route.authentication.refresh=refresh
    jwt.route.authentication.register=auth/register

    # logging
    logging.level.org.springframework.data=DEBUG
    logging.level.org.springframework.security=DEBUG
  • 2b685e075c4d:好像有点问题,每次请求,token的那个过滤器执行了二次,是为什么啊?
    d919d7b0eb7e:刚接触spring security,我同样也有这个问题。请问你现在找到原因了吗?
  • 嘿嘿嘿的我: @Override
    public String login(String username, String password) {
    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken=new UsernamePasswordAuthenticationToken(username,password);
    Authentication authentication=authenticationManager.authenticate(usernamePasswordAuthenticationToken);
    SecurityContextHolder.getContext().setAuthentication(authentication);
    UserDetails userDetails= userDetailsService.loadUserByUsername(username);
    String token = jwtTokenUtil.generateToken(userDetails);
    return token;
    }
    获得token时postman显示、
    {
    "timestamp": 1501205673323,
    "status": 403,
    "error": "Forbidden",
    "exception": "org.springframework.security.authentication.InternalAuthenticationServiceException",
    "message": "Access Denied",
    "path": "/auth"
    }
    没有任何错误信息
    然后我打断点看发现这句有问题,但是我不清楚什么原因
    Authentication authentication=authenticationManager.authenticate(usernamePasswordAuthenticationToken);
    0135b9553aeb:一样卡在这里 非常尴尬 寻找答案中
    Ray916:我的问题好像跟你差不多,但是输入的用户名密码是对的啊:joy:
    接灰的电子产品:问题在哪,用户验证未通过就会返回这个
  • 我本佛山人:你好,有与JWT与Shiro整合的吗?同时如果使用了JWT,那么是否就不再需要Spring-session了呢?JWT生成的token我是保存在Redis中的
  • edefb1629f21:还有作为一个初学者,这个这样打断点调试
  • edefb1629f21:按照 你的方式搭建了,根目录访问不了啊, Secure object: FilterInvocation: URL: /; Attributes: [hasAnyRole('ROLE_USER')]
    2017-07-13 19:50:47.051 DEBUG 13164 --- [nio-9000-exec-1] o.s.s.w.a.i.FilterSecurityInterceptor : Previously Authenticated: org.springframework.security.authentication.AnonymousAuthenticationToken@9055c2bc: Principal: anonymousUser; Credentials: [PROTECTED]; Authenticated: true; Details: org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null; Granted Authorities: ROLE_ANONYMOUS
    2017-07-13 19:50:47.054 DEBUG 13164 --- [nio-9000-exec-1] o.s.s.access.vote.AffirmativeBased : Voter: org.springframework.security.web.access.expression.WebExpressionVoter@7f7a76a5, returned: -1
    2017-07-13 19:50:47.057 DEBUG 13164 --- [nio-9000-exec-1] o.s.s.w.a.ExceptionTranslationFilter : Access is denied (user is anonymous); redirecting to authentication entry point
    求解啊
  • edefb1629f21:请教下楼主:按照你的方式,跟目录页范围不了啊,楼主可以留下qq不,这样方便交流
  • 1773639db823:楼主好,这个动静态分离的情况下,ajax设置token到请求头,跨域的情况下那个filter是不是获取不到token?
    接灰的电子产品:可以,跨域看第五章
  • 大强_89b7:楼主好,能提供源码吗?谢谢
    接灰的电子产品:文章中给了github地址
  • 这时对那时错:如果被人挤掉了 以前token怎么办啊 放redis里吗 还是咋搞
  • camlboy:很详细的教程,赞赞赞
  • AzureSerenity:感谢详细的例子和说明,后端新手表示学习了
  • Angeladaddy:今天试了下代码,发现一处问题补充一下:
    这个代码用postman是没有任何问题的,但是如果加上跨域+ajax请求,浏览器报错,打断点发现问题出在JwtAuthenticationTokenFilter这里,拦截器根本拦截不到Authorization这个Header,postman就可以...
    度娘得知,前端这种跨域请求是两次查询,第一次是Option,服务端返回状态给前端,前端才会据此发起第二次真实请求。自己改了下代码,斗胆贴一下:
    ```
    @Override
    protected void doFilterInternal(
    HttpServletRequest request,
    HttpServletResponse response,
    FilterChain chain) throws ServletException, IOException {
    //设置response,否则前端页面拿不到option结果
    response.setCharacterEncoding("UTF-8");
    response.setContentType("application/json;charset=utf-8");
    response.setHeader("Access-Control-Allow-Origin", "*");
    response.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
    response.setHeader("Access-Control-Allow-Headers","Authorization");
    String method = request.getMethod();
    if(method.equals("OPTIONS")){
    //预请求需要往回写 让ajax预请求知道预请求是成功的
    response.setStatus(202);
    response.getWriter().write(1);
    }
    else{
    //取得header
    String authHeader = request.getHeader(this.tokenHeader);
    *****以下为原本内容

    ```
    接灰的电子产品:不能吧,我改天试试,我记得当初是拿angular验证过的
    Angeladaddy:跨域加上也不行的,老大,你试试,这个地方就是获取不到,我卡在这一天了:sweat:
    接灰的电子产品:@Angeladaddy 哈哈,不错,但其实你没看第五篇,讲的是跨域:smile:
  • 8c4523b79edf:同问,请教下,既然定义了role表 ,为什么在security的权限控制里还是把角色写死在方法上了?如果要根据当前用户的角色动态验证所属角色的权限应该在哪里实现,该如何配置呢?
    肖老板:自己实现PermissionEvaluator接口即可
  • 接灰的电子产品:系列第四篇
    suman11:@接灰的电子产品 非常感谢。我都追到你的掘金专栏里面,看到git了 :)
    接灰的电子产品:@suman11 文尾
    suman11:git连接能给一个吗。谢谢
  • Angeladaddy:老大,例子中的JwtTokenUtil没有给出啊,意思是让我们自己写一个?
    bc8cdd63ae38:如果是跨域情况下,默认会先请求服务器是否允许跨域,然后再发送真实的请求,这种情况下的拦截机制应该怎么实现呢?有朋友可以给予帮助吗?
    接灰的电子产品:看github,上面有
  • c000d21140e9:如果是多个微服务怎么解决单点登录授权啊?如user服务用来登录,category服务用来获取类目;那么在user服务登录后,再请求category的接口呢?
    接灰的电子产品:@北极以北_0f95 用spring cloud当然可以
    c000d21140e9:这个api server是路由吧,用的spring cloud吗?
    接灰的电子产品:@北极以北_0f95 我一般做一个api server作为facade,然后在服务器端做微服务的转发,各个微服务用token认证彼此的通讯
  • 9acf42ee1cd6: 大神有没有用maven搭建的例子,一直在用maven做,看着gradle感觉挺别扭,看了一些其他token验证的一直没看明白,感觉好难
    接灰的电子产品:maven的改造不难啊,就是gradle改成xml,用idea建项目时采用maven即可啊
  • 6e81c91b133d:请问下 原生的spring cloud security的JWT 该如何logout
    接灰的电子产品:@天空中最亮的昕 没明白你的意思,其实最简单的logout就是客户端直接清空token即可。如果你希望token失效,可以在服务端做
  • Nathans:自定义实现过滤器时有点问题想请教下
    Nathans:@接灰的电子产品 动态控制URL权限,而不是通过Annotation的PreAuthorize方式去控制。
    接灰的电子产品:@Nathans 童鞋,你这不合规矩啊。第一:这个问题和我文章无关,如果单纯想问有关问题的话,建议去stackoverflow问。第二:得学会问问题,你的代码要秀一下吧,想要达到的目的要说一下吧,然后才是现在遇到的问题。
    接灰的电子产品:@Nathans 请讲
  • eddy_shen:可以:+1:
  • 04189ac4f18d:请教个问题

    @Override
    public String login(String username, String password) {
    UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(username, password);
    final Authentication authentication = authenticationManager.authenticate(upToken);
    SecurityContextHolder.getContext().setAuthentication(authentication);

    final UserDetails userDetails = userDetailsService.loadUserByUsername(username);
    final String token = jwtTokenUtil.generateToken(userDetails);
    return token;
    }
    这一段中,
    UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(username, password);
    final Authentication authentication = authenticationManager.authenticate(upToken);
    SecurityContextHolder.getContext().setAuthentication(authentication);
    这一部分的作用是什么呢?
    我看也没有验证用户名密码的正确性,那岂不是什么密码都可以获取token了么?
    谢谢啦
    接灰的电子产品:@木头壳 这个是spring security完成的,你给它提供一个loadbyusername的方法,它会去做验证的,你可以设断点逐步跟踪一下就知道了
    04189ac4f18d:@接灰的电子产品 我看您的github仓库里面的事例代码JwtUserDetailsServiceImpl 中也没有做验证呀?
    接灰的电子产品:AuthenticationManager 是Spring Secrurity提供的,它会根据我们实现的UserDetailServiceImpl去进行用户验证的
  • 70342eb43d60:请问这篇文章是完整的代码吗?还是只是一部分代码
    接灰的电子产品:@jianandgui 原理就是那样,你可以按你的想法做就好
    70342eb43d60:@接灰的电子产品 我看了,好多阿,是不是复杂化了 ?:joy:
    接灰的电子产品:@jianandgui github上有完整代码
  • 帅气小伙:你的更新Token的代码有点异常哦
    io.jsonwebtoken.MalformedJwtException: Unable to read JSON value: �����!L��ȉ
    这个是异常信息,在 getClaimsFromToken 方法。
    帅气小伙: @接灰的电子产品 我在用你的代码实现前后端分离,效果还行。
    接灰的电子产品:@帅气小伙 这个和普通API访问是一样的,都需要添加Bearer,异常处理不是本文的重点,可以根据自己的业务去做。
    帅气小伙:报这个异常的原因,是因为需要在获取的Token前增加持票人,即Bearer +token。所以在刷新token的时候应该判断一下是否含有Bearer
  • 啊心:你好,个人觉得采用这种方案做移动端的接口安全也挺合适,不知道还有什么其他地方需要注意的吗
    接灰的电子产品:@啊心 对啊,移动端也一样的,但是需要注意本地token最好也加密,而且在服务端应该通过ip地址是否常用ip,登录频率等等综合判定是否让用户重新登录还是可以直接使用token
  • JingGo:例子详细,赞一个!!!:+1:
  • e01edda0af05:请求几个问题:
    1、客户端请求登录--->验证通过---->服务端生成token发送给客户端 前 服务端是否要保存?
    2、客户端带token再次请求,服务端获取客户端的token解密后,服务端根据什么依据对比?
    3、客户端登录验证后,得到token,希望在没退出、浏览器没关闭前一直有效,怎么做?
    其它三个问题应该算是一个了!
    接灰的电子产品:@半隻饅頭 所有token都有这个问题啊,所有的目前开放api也都是这么做的,如果你的微博api token被别人知道了,一样的效果。所以要有其他的安全策略配合,比如结合访问者域名,ip,访问频率等等。
    e01edda0af05:@接灰的电子产品 如果别人拿到这个token是不是可以一直请求?
    接灰的电子产品:@半隻饅頭 token的验证是通过密钥解开的,所以不需要服务端保存,能解开就是对的。客户端token保持策略需要你根据你的业务确定,是保存在cookie或localstorage中。当然如果追求进一步的安全性的话,可以采用每个客户token的密钥都不相同,此时就需要服务器数据库保存各个客户token对应的密钥。
  • Angeladaddy:正需要,已转发给后端同学学习,
    另,我觉得你应该考虑出本书了,认真的
    Angeladaddy:@接灰的电子产品 :+1::+1::+1:第一时间去买
    接灰的电子产品:@Angeladaddy angular系列应该近期就有纸书了,快要预售了:smile:

本文标题:重拾后端之Spring Boot(四):使用JWT和Spring

本文链接:https://www.haomeiwen.com/subject/cspogttx.html