我正在使用go-swagger,BearerAuth
使用JWT令牌。除了实际的令牌外,我还收到了包含用户名等数据的声明。
如何在下面的api.ItemsCreateItemHandler
函数中访问声明?
package restapi
func configureAPI(api *operations.MyAPI) http.Handler {
api.BearerAuth = func(token string) (interface{}, error) {
jwtToken := strings.Replace(token, "Bearer ", "", -1)
// skipped token verification
claims, _ := parsedToken.Claims.(jwt.MapClaims)
}
api.ItemsCreateItemHandler = items.CreateItemHandlerFunc(func(params items.CreateItemParams, principal interface{}) middleware.Responder {
// FIXME: Here I need to be able to access JWT claims
if err := createItem(params.Body, claims); err != nil {
return nil // handle error
}
return items.NewCreateItemCreated()
})
}
首先,BearerAuth
实现旨在返回安全主体(在本例中可以是您的声明(,此值随后将在principal
参数中传递给您的处理程序。
所以这样做的方法是:
package restapi
import (
jwt "github.com/dgrijalva/jwt-go"
// ...
)
func configureAPI(api *operations.MyAPI) http.Handler {
api.BearerAuth = func(token string) (interface{}, error) {
jwtToken := strings.Replace(token, "Bearer ", "", -1)
// skipped token verification
claims, _ := parsedToken.Claims.(jwt.MapClaims)
return claims, nil
}
api.ItemsCreateItemHandler = items.CreateItemHandlerFunc(func(params items.CreateItemParams, principal interface{}) middleware.Responder {
claims, ok := principal.(jwt.MapClaims)
if !ok {
// handle error
}
if err := createItem(params.Body, claims); err != nil {
return nil // handle error
}
return items.NewCreateItemCreated()
})
}
您可以通过使用--principal jwt.MapClaims
选项进行swagger generate
来减少繁琐,以便它将此类型用于声明而不是interface{}
。
JWT 由 3 个部分组成,按标点符号拆分 - 令牌本身是 base64 编码的。
例如,这里有一个来自 https://jwt.io/的令牌
eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiaWF0IjoxNTE2MjM5MDIyfQ.SflKxwRJSMeKKF2QT4fwpMeJf36POk6yJV_adQssw5c
您需要拆分和解码,您是在第二部分之后,其中包含只是普通 JSON 的有效负载。
所以在伪代码中,它看起来像这样;
json = Base64Decode(split(".", yourData)[1])
您将在 https://jwt.io/中看到更具体的示例
我有一个存储令牌并包含解析方法的类:
import io.jsonwebtoken.*;
@AllArgsConstructor
public class RawAccessJwtToken implements JwtToken {
private String token;
@Override
public String getToken() {
return token;
}
public Jws<Claims> parseClaims(String signingKey) {
try {
return Jwts.parser().setSigningKey(signingKey).parseClaimsJws(this.token);
} catch (UnsupportedJwtException | MalformedJwtException | IllegalArgumentException e) {
throw new BadCredentialsException("Invalid JWT token: " + e);
} catch (ExpiredJwtException expiredException){
throw new JwtExpiredTokenException(this, "JWT Token expired", expiredException);
}
}
}
使用该类,我可以提取我的用户角色:
Jws<Claims> claimsJws = token.parseClaims(signingKey);
List<String> scopes = claimsJws.getBody().get("scopes",
List.class);