英文:
JSON Web Token (JWT): should I use response header or body for token transportation?
问题
我正在开发一个RESTful web服务,用于颁发**JSON Web Tokens (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());
}
}
英文:
I'm developing a RESTful web service that issues access tokens in the form of JSON Web Tokens (JWT), so that clients can use them for further authorization. Currently, I store tokens in a response body, but typically it's advised to add it to Authorization header. Why should I choose header and not response body? Is there any principal advantage on using one method over the other?
@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
得分: 3
这是HTTP标准的一部分,所有API都要遵循。简单来说,可以将其视为一组规则,每个人都遵循这些规则,以便在开发服务器或客户端时,可以遵循这些规则以避免不一致。
RFC链接:https://www.rfc-editor.org/rfc/rfc7235#section-4.2
"Authorization"头字段允许用户代理在通常情况下(但不一定是在收到401(未经授权)响应后)与源服务器进行身份验证。其值包含用户代理的身份验证信息,用于请求的资源领域。
Authorization = credentials
现在有许多不同类型的授权头,人们可以使用,一旦使用,就知道可以期望什么。以下是一个简单的列表,展示了一些类型:
- 基本身份验证(Basic Auth)
- 令牌身份验证(Bearer Token)
- API密钥(API Key)
- 摘要身份验证(Digest Auth)
- OAuth 2.0
- Hawk身份验证(Hawk Authentication)
- AWS签名(AWS Signature)
英文:
It is part of the HTTP standard which all api follow. In basic terms think of a set of rules that everyone follows so that when people develop servers or clients then they can follow this set of rules to avoid discrepancies
RFC https://www.rfc-editor.org/rfc/rfc7235#section-4.2
> The "Authorization" header field allows a user agent to authenticate
> itself with an origin server -- usually, but not necessarily, after
> receiving a 401 (Unauthorized) response. Its value consists of
> credentials containing the authentication information of the user
> agent for the realm of the resource being requested.
>
> Authorization = credentials
There are many different types of authorization headers that people can use right now and once you use it then you know what to expect. Here is a simple list to show a few
• Basic Auth
• Bearer Token
• API Key
• Digest Auth
• Oauth 2.0
• Hawk Authentication
• AWS Signature
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论