Java 通过基本身份验证端点创建JSON Web令牌?Dropwizard
使用Dropwizard 1.2.0和,我试图从名为Java 通过基本身份验证端点创建JSON Web令牌?Dropwizard,java,jwt,dropwizard,Java,Jwt,Dropwizard,使用Dropwizard 1.2.0和,我试图从名为/tokenAPI端点创建json web令牌 此端点要求客户端使用基本身份验证方法传递用户名和密码。如果成功,响应将包含JSON web令牌 负责人 public class ShepherdAuth implements JwtCookiePrincipal { private String name; private Set<String> roles; public ShepherdAuth(String name, S
/token
API端点创建json web令牌
此端点要求客户端使用基本身份验证方法传递用户名和密码。如果成功,响应将包含JSON web令牌
负责人
public class ShepherdAuth implements JwtCookiePrincipal {
private String name;
private Set<String> roles;
public ShepherdAuth(String name, Set<String> roles) {
this.name = checkNotNull(name, "User name is required");
this.roles = checkNotNull(roles, "Roles are required");
}
@Override
public boolean isPersistent() {
return false;
}
@Override
public boolean isInRole(final String s) {
return false;
}
@Override
public String getName() {
return this.name;
}
@Override
public boolean implies(Subject subject) {
return false;
}
public Set<String> getRoles() {
return roles;
}
}
App/Config
@Override
public void run(final ShepherdServiceConfiguration configuration,
final Environment environment) {
final ShepherdController shepherdController = new ShepherdController();
// app authentication
environment.jersey().register(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<ShepherdAuth>()
.setAuthenticator(new ShepherdAuthenticator())
.setAuthorizer(new ShepherdAuthorizer())
.setRealm(configuration.getName())
.buildAuthFilter()));
@覆盖
公共无效运行(最终ShepherdServiceConfiguration配置,
最终环境(环境){
最终ShepherdController ShepherdController=新的ShepherdController();
//应用程序身份验证
environment.jersey().register(新的AuthDynamicFeature(新的BasicCredentialAuthFilter.Builder())
.setAuthenticator(新的ShepherdAuthenticator())
.setAuthorizer(新的牧羊人授权人())
.setRealm(配置.getName())
.buildAuthFilter());
当我尝试向/shepherd/token
发出请求时,我没有收到关于基本身份验证的提示,而是收到一个HTTP 401响应,其中包含
访问此资源需要凭据
如何让控制器提示输入用户名和密码,并在成功时生成JWT?我在项目中通过使用实现了JWT令牌,但解决方案很容易应用到另一个库。诀窍是使用不同的身份验证程序 这个答案不适用于,但在为Dropwizard提供JWT方面做得很好:) 首先,申请:
environment.jersey().register(new TokenResource(configuration.getJwsSecretKey()));
environment.jersey().register(new HelloResource());
environment.jersey().register(RolesAllowedDynamicFeature.class);
environment.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));
environment.jersey()
.register(
new AuthDynamicFeature(
new ChainedAuthFilter<>(
Arrays
.asList(
new JWTCredentialAuthFilter.Builder<User>()
.setAuthenticator(
new JWTAuthenticator(configuration.getJwsSecretKey()))
.setPrefix("Bearer").setAuthorizer(new UserAuthorizer())
.buildAuthFilter(),
new JWTDefaultCredentialAuthFilter.Builder<User>()
.setAuthenticator(new JWTDefaultAuthenticator())
.setAuthorizer(new UserAuthorizer()).setRealm("SUPER SECRET STUFF")
.buildAuthFilter()))));
这里,TokenResource
是令牌供应资源,HelloResource
是我们的测试资源。User
是主体,如下所示:
public class User implements Principal {
private String name;
private String password;
...
}
还有一个类用于传递JWT令牌:
public class JWTCredentials {
private String jwtToken;
...
}
TokenResource
使用密码“test”为用户“test”提供令牌:
而HelloResource
只是回显用户:
@GET
@RolesAllowed({"ANY"})
public String hello(@Auth User user) {
return "hello user \"" + user.getName() + "\"";
}
JWTCredentialAuthFilter
为两种身份验证方案提供凭据:
@Priority(Priorities.AUTHENTICATION)
public class JWTCredentialAuthFilter<P extends Principal> extends AuthFilter<JWTCredentials, P> {
public static class Builder<P extends Principal>
extends AuthFilterBuilder<JWTCredentials, P, JWTCredentialAuthFilter<P>> {
@Override
protected JWTCredentialAuthFilter<P> newInstance() {
return new JWTCredentialAuthFilter<>();
}
}
@Override
public void filter(ContainerRequestContext requestContext) throws IOException {
final JWTCredentials credentials =
getCredentials(requestContext.getHeaders().getFirst(HttpHeaders.AUTHORIZATION));
if (!authenticate(requestContext, credentials, "JWT")) {
throw new WebApplicationException(
this.unauthorizedHandler.buildResponse(this.prefix, this.realm));
}
}
private static JWTCredentials getCredentials(String authLine) {
if (authLine != null && authLine.startsWith("Bearer ")) {
JWTCredentials result = new JWTCredentials();
result.setJwtToken(authLine.substring(7));
return result;
}
return null;
}
}
JWTDefaultAuthenticator
在不存在凭据时,为代码提供一个空用户:
public class JWTDefaultAuthenticator implements Authenticator<JWTCredentials, User> {
@Override
public Optional<User> authenticate(JWTCredentials credentials) throws AuthenticationException {
return Optional.of(new User());
}
}
如果一切顺利
curl -s -X POST -d 'test' http://localhost:8080/token/test
将为您提供如下信息:
eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MDk3MDYwMjYsInN1YiI6InRlc3QifQ.ZrRmWTUDpaA6JlU4ysIcFllxtqvUS2OPbCMJgyou_tY
这个问题呢
curl -s -X POST -d 'xtest' http://localhost:8080/token/test
将以失败告终
{"code":401,"message":"HTTP 401 Unauthorized"}
(顺便说一句,URL中的“test”是用户名,post数据中的“test”是密码。与基本身份验证一样简单,可以为CORS配置。)
请求呢
curl -s -X GET -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MDk3MDYwMjYsInN1YiI6InRlc3QifQ.ZrRmWTUDpaA6JlU4ysIcFllxtqvUS2OPbCMJgyou_tY' http://localhost:8080/hello
将显示
hello user "test"
当
及
将导致
{"code":403,"message":"User not authorized."}
您的配置中缺少此行
environment.jersey().register(新AuthValueFactoryProvider.Binder(User.class));
谢谢,但此库不稳定,仅为0.9.0版:(两件事:不要让版本误导您,我知道Dropwizard在版本1之前已经用于许多不同的生产环境。其次,Dropwizard JWT库使用同一个库。请检查它的pom.xml。谢谢,我尝试了您的解决方案,但它说它找不到JWTCredentials
类,我必须这样做吗由另一个库提供?我的不好。编辑了答案以包含它。它只是一个仅具有jwtToken
属性的POJO。感谢您的帮助,是否仍然可以使用TokenResource
而不是DefaultJWTAuthenticator的基本身份验证?我尝试将BasicCredentialAuthFilter
添加到身份验证器列表b中尝试使用该端点获取令牌时,Dropwizard没有提示登录。有什么想法吗?
eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MDk3MDYwMjYsInN1YiI6InRlc3QifQ.ZrRmWTUDpaA6JlU4ysIcFllxtqvUS2OPbCMJgyou_tY
curl -s -X POST -d 'xtest' http://localhost:8080/token/test
{"code":401,"message":"HTTP 401 Unauthorized"}
curl -s -X GET -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiJ9.eyJpYXQiOjE1MDk3MDYwMjYsInN1YiI6InRlc3QifQ.ZrRmWTUDpaA6JlU4ysIcFllxtqvUS2OPbCMJgyou_tY' http://localhost:8080/hello
hello user "test"
curl -s -X GET -H 'Authorization: Bearer invalid' http://localhost:8080/hello
curl -s -X GET http://localhost:8080/hello
{"code":403,"message":"User not authorized."}