【问题标题】:How JSON web token works in Spring boot?JSON Web 令牌如何在 Spring Boot 中工作?
【发布时间】:2018-06-14 09:55:18
【问题描述】:

我想编写 REST 服务,我选择 JWT 来保护这个 REST 服务。
我声明了 1 分钟的令牌,之后我必须做什么?
我必须刷新令牌或其他东西?

如果我必须刷新令牌,用户可以用这个令牌调用服务的方法吗?

令牌代码

package com.example.demo.config;

import java.util.Date;
import java.util.List;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import java.util.ArrayList;
import java.util.Arrays;

public class TokenAuthenticationService {

    //field of conf
    static final long EXPIRATIONTIME = 60_000; // 1 min
    static final String SECRET = "msg";
    static final String TOKEN_PREFIX = "Bearer";
    static final String HEADER_STRING = "Authorization";

    //generate token
    public static void addAuthentication(HttpServletResponse res, Authentication auth) {
        String concattedRoles = "";
        for (GrantedAuthority ga : auth.getAuthorities()) {
            if (!"".equals(concattedRoles))
                 concattedRoles += "," + ga.getAuthority();
             else
                 concattedRoles += ga.getAuthority();
        }
        String JWT = Jwts.builder().setSubject(auth.getName()).claim("roles", concattedRoles)
                .setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
                .signWith(SignatureAlgorithm.HS512, SECRET).compact();
        res.addHeader(HEADER_STRING, TOKEN_PREFIX + " " + JWT);
    }

    //get token from request header.
    public static Authentication getAuthentication(HttpServletRequest request) {
        try {
            System.out.println("(Authentication getAuthentication(HttpServletRequest request)");
            String token = request.getHeader(HEADER_STRING);
            System.out.println("token=>"+token);
            if (token != null) {
                Claims claims = Jwts.parser().setSigningKey(SECRET).parseClaimsJws(token.replace(TOKEN_PREFIX, "")).getBody();
                String user = claims.getSubject();
                String roles = (String) claims.get("roles");

                if(claims.getExpiration().before(new Date(System.currentTimeMillis())))
                    throw new Exception(); //Here trow exception.
                List<String> roleList = Arrays.asList(roles.split("\\s*,\\s*"));
                List<GrantedAuthority> grantedAuths = new ArrayList<GrantedAuthority>();
                for (int i = 0; i < roleList.size(); i++) {
                    System.out.println(roleList.get(i));
                    SimpleGrantedAuthority abv = new SimpleGrantedAuthority(roleList.get(i));
                    grantedAuths.add(abv);
                }
                System.out.println(grantedAuths);
                return user != null ? new UsernamePasswordAuthenticationToken(user, null, grantedAuths) : null;
            }
            return null;
        }catch (Exception e){
            System.out.println(e);
            return null;
        }
    }

}

【问题讨论】:

  • 也许尝试在每次请求后刷新用户的当前令牌并将其发回?
  • 如果我刷新用户的当前令牌,为什么我必须发送回?用户可以继续使用第一个令牌调用我的服务吗?如果是,用户将如何获得新令牌?
  • 好吧,我知道这如何与标头一起使用,但与 cookie 一起使用时效果很好。当用户提出请求时,您检查他的 JWT-cookie。如果没问题,在请求之后你只需放置另一个同名的 JWT cookie,但修改了过期时间。结果,用户将在其 cookie 中更新 JWT。
  • 用户不会使用浏览器。我想如下。首先,用户将使用用户数据(用户名,密码)向我的 htt://blablba/v1.0/login 发送请求,然后我将为该用户发送令牌。第二次或另一次用户通过此令牌调用我的服务的方法。你说刷新令牌。那个时候用户必须为不同的请求获取新的令牌。这是正常的方式吗?
  • 我检查令牌过期时间的预览示例,如果令牌过期,则抛出异常,用户将得到 403“拒绝访问”。但我不知道这是否正常?

标签: java spring spring-boot spring-security jwt


【解决方案1】:

我们是如何实现的——

  1. 用户首次登录时,我们会向他们发送一个令牌和一个刷新令牌。
  2. 客户端然后使用标头中的“令牌”进行进一步的 API 调用。
  3. 在客户端,我们保持 15 分钟的倒计时(小于主令牌的到期时间),之后我们从客户端向服务器发送带有令牌和刷新令牌的请求。
  4. 在获得一个有效的刷新令牌和主令牌后,服务器会发回一个新的令牌并增加过期时间。

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    基本上refresh_token 用于根据请求向用户返回有效的access_token。而refresh_tokens 通常是长期存在的,而不是短暂的。

    就个人而言,我保护 RESTful API 的设计只是让他们向我的端点请求access_token,即https://api.example.com/oauth/token每次,我不提供refresh_token,因为我的想法只是让他们进入资源,没有别的。通常,请求资源不会在特定会话上停留这么长时间。对于服务器在同一用户/会话上收到过多请求的其他问题,您可以在您的服务器或令牌端点上实现 rate-limiting

    我的 API 安全实现基于 PayPalJHipster。他们没有为各自的 RESTful API 实现提供refresh_tokens,因为最后,refresh_tokens 是可选的,这只是您在保护 RESTful 端点时想要实现的目标。

    有关refresh_token 的更多信息,您可以访问以下链接: When to use JWT TokensUnderstanding refresh tokens

    【讨论】:

      猜你喜欢
      • 2017-04-16
      • 2020-01-12
      • 2018-09-27
      • 2019-05-12
      • 2017-01-01
      • 2016-12-20
      • 1970-01-01
      • 2021-06-16
      • 2017-06-18
      相关资源
      最近更新 更多