JSON Web 令牌 (JWT):我应该使用响应标头还是正文进行令牌传输?
Posted
技术标签:
【中文标题】JSON Web 令牌 (JWT):我应该使用响应标头还是正文进行令牌传输?【英文标题】:JSON Web Token (JWT): should I use response header or body for token transportation? 【发布时间】:2020-12-24 21:50:35 【问题描述】:我正在开发一个 RESTful Web 服务,它以 JSON Web 令牌 (JWT) 的形式发布访问令牌,以便客户端可以使用它们进行进一步授权。目前,我将令牌存储在响应正文中,但通常建议将其添加到 Authorization 标头中。为什么我应该选择标题而不是响应正文?使用一种方法比另一种方法有什么主要优势吗?
@RestController
@RequestMapping(path = "/auth", produces = "application/json")
public class AccessTokenController
@Value("$jwt.secret.key.gen")
private String secretKey;
@Value("$jwt.expiration.days")
private int expirationDays;
private final UsersRepository usersRepository;
private final PasswordEncoder passwordEncoder;
@Autowired
public AccessTokenController(UsersRepository usersRepository, PasswordEncoder passwordEncoder)
this.usersRepository = usersRepository;
this.passwordEncoder = passwordEncoder;
@PostMapping(value = "/access-token", consumes = "application/json")
ResponseEntity<Object> getAccessToken(@RequestBody Map<String, String> credentials)
// #1: check request body for username and password
String username = credentials.get("username");
String password = credentials.get("password");
if (username.isBlank() || password.isBlank())
throw new IllegalArgumentException();
// #2: check database for given username and password
User user = usersRepository.findByUsername(username)
.filter(u -> passwordEncoder.matches(password, u.getPassword()))
.orElseThrow(() -> new BadCredentialsException("No such user with given password"));
// #3: check 'enabled' status for the requested user
if (!user.isEnabled())
throw new DisabledException("User is currently disabled");
// # 4: create and return access-token (finally!)
String token = Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + expirationDays * 24 * 60 * 60 * 1000))
.signWith(SignatureAlgorithm.HS512, secretKey.getBytes())
.compact();
return new ResponseEntity<>(Collections.singletonMap("access-token", token),
HttpStatus.OK);
@ExceptionHandler(JsonParseException.class, NullPointerException.class, IllegalArgumentException.class)
@ResponseStatus(HttpStatus.BAD_REQUEST)
public Map<String, String> handleWrongOrMissingCredentials()
return Collections.singletonMap("error", "Wrong or missing credentials");
@ExceptionHandler(AuthenticationException.class)
@ResponseStatus(HttpStatus.UNAUTHORIZED)
public Map<String, String> handleAuthenticationException(AuthenticationException ex)
return Collections.singletonMap("error", ex.getMessage());
【问题讨论】:
【参考方案1】:它是所有 api 都遵循的 HTTP 标准的一部分。基本上,想出一套每个人都遵循的规则,这样当人们开发服务器或客户端时,他们就可以遵循这套规则以避免差异
RFC https://www.rfc-editor.org/rfc/rfc7235#section-4.2
“授权”标头字段允许用户代理进行身份验证 本身带有源服务器——通常但不一定是在之后 收到 401(未经授权)响应。它的价值包括 包含用户身份验证信息的凭据 被请求资源领域的代理。
Authorization = credentials
人们现在可以使用许多不同类型的授权标头,一旦您使用它,您就会知道会发生什么。这是一个简单的列表来展示一些
• Basic Auth
• Bearer Token
• API Key
• Digest Auth
• Oauth 2.0
• Hawk Authentication
• AWS Signature
【讨论】:
以上是关于JSON Web 令牌 (JWT):我应该使用响应标头还是正文进行令牌传输?的主要内容,如果未能解决你的问题,请参考以下文章
为啥要使用环境变量对 JSON Web 令牌 (JWT) 进行签名?
如何在 C# AspNetCore 网站中使用 JWT JSON Web 令牌?
我应该在哪里存储“非单页”前端应用程序的 JSON Web 令牌