原文: https://howtodoinjava.com/dropwizard/dropwizard-basic-auth-security-example/
使用 dropwizard,我们了解了创建 REST API ,编写客户端代码和添加运行状况检查过滤器的知识。 在本教程中,我们将学习使用基本认证将基于用户名/密码的认证和基于基于角色的授权功能添加到 REST API 中。
Table of ContentsInclude Dropwizard Auth Module Maven DependencyAdd Custom Principal ObjectAdd Custom AuthenticatorAdd Custom AuthorizerConfigure BasicCredentialAuthFilterSecure REST APIs with @Auth AnnotationTest Dropwizard Basic Auth Code
包含 Dropwizard Auth 模块的 Maven 依赖项
认证功能在 dropwizard 应用中作为单独的模块添加。
<properties><dropwizard.version>1.0.0</dropwizard.version></properties><dependency><groupId>io.dropwizard</groupId><artifactId>dropwizard-auth</artifactId><version>${dropwizard.version}</version></dependency>
添加自定义主体对象
在安全性方面,主体对象表示已为其提供凭据的用户。 它实现了java.security.Principal接口。
package com.howtodoinjava.rest.auth;import java.security.Principal;import java.util.Set;public class User implements Principal {private final String name;private final Set<String> roles;public User(String name) {this.name = name;this.roles = null;}public User(String name, Set<String> roles) {this.name = name;this.roles = roles;}public String getName() {return name;}public int getId() {return (int) (Math.random() * 100);}public Set<String> getRoles() {return roles;}}
添加自定义认证器
Authenticator类负责验证基本认证标头中包含的用户名/密码凭证。 在企业应用中,您可以从数据库中获取用户密码,如果密码匹配,则将用户角色设置为主体对象。 在 dropwizard 中,您将需要实现io.dropwizard.auth.Authenticator接口以放置您的应用逻辑。
package com.howtodoinjava.rest.auth;import io.dropwizard.auth.AuthenticationException;import io.dropwizard.auth.Authenticator;import io.dropwizard.auth.basic.BasicCredentials;import java.util.Map;import java.util.Optional;import java.util.Set;import com.google.common.collect.ImmutableMap;import com.google.common.collect.ImmutableSet;public class AppBasicAuthenticator implements Authenticator<BasicCredentials, User>{private static final Map<String, Set<String>> VALID_USERS = ImmutableMap.of("guest", ImmutableSet.of(),"user", ImmutableSet.of("USER"),"admin", ImmutableSet.of("ADMIN", "USER"));@Overridepublic Optional<User> authenticate(BasicCredentials credentials) throws AuthenticationException{if (VALID_USERS.containsKey(credentials.getUsername()) && "password".equals(credentials.getPassword())){return Optional.of(new User(credentials.getUsername(), VALID_USERS.get(credentials.getUsername())));}return Optional.empty();}}
添加自定义授权器
Authorizer类负责匹配角色,并确定是否允许用户执行某些操作。
package com.howtodoinjava.rest.auth;import io.dropwizard.auth.Authorizer;public class AppAuthorizer implements Authorizer<User>{@Overridepublic boolean authorize(User user, String role) {return user.getRoles() != null && user.getRoles().contains(role);}}
配置BasicCredentialAuthFilter
现在,让我们将自定义类注册到 dropwizard 安全框架中。
package com.howtodoinjava.rest;import io.dropwizard.Application;import io.dropwizard.Configuration;import io.dropwizard.auth.AuthDynamicFeature;import io.dropwizard.auth.AuthValueFactoryProvider;import io.dropwizard.auth.basic.BasicCredentialAuthFilter;import io.dropwizard.client.JerseyClientBuilder;import io.dropwizard.setup.Bootstrap;import io.dropwizard.setup.Environment;import javax.ws.rs.client.Client;import org.glassfish.jersey.server.filter.RolesAllowedDynamicFeature;import com.howtodoinjava.rest.auth.AppAuthorizer;import com.howtodoinjava.rest.auth.AppBasicAuthenticator;import com.howtodoinjava.rest.auth.User;import com.howtodoinjava.rest.controller.EmployeeRESTController;import com.howtodoinjava.rest.controller.RESTClientController;import com.howtodoinjava.rest.healthcheck.AppHealthCheck;import com.howtodoinjava.rest.healthcheck.HealthCheckController;public class App extends Application<Configuration> {@Overridepublic void initialize(Bootstrap<Configuration> b) {}@Overridepublic void run(Configuration c, Environment e) throws Exception {e.jersey().register(new EmployeeRESTController(e.getValidator()));final Client client = new JerseyClientBuilder(e).build("DemoRESTClient");e.jersey().register(new RESTClientController(client));// Application health checke.healthChecks().register("APIHealthCheck", new AppHealthCheck(client));// Run multiple health checkse.jersey().register(new HealthCheckController(e.healthChecks()));//****** Dropwizard security - custom classes ***********/e.jersey().register(new AuthDynamicFeature(new BasicCredentialAuthFilter.Builder<User>().setAuthenticator(new AppBasicAuthenticator()).setAuthorizer(new AppAuthorizer()).setRealm("BASIC-AUTH-REALM").buildAuthFilter()));e.jersey().register(RolesAllowedDynamicFeature.class);e.jersey().register(new AuthValueFactoryProvider.Binder<>(User.class));}public static void main(String[] args) throws Exception {new App().run(args);}}
具有@Auth注解的安全 REST API
添加@Auth注解将在将其作为参数的任何 API 上触发认证过滤器。
1)用户必须经过验证。 允许所有用户使用 API。
@PermitAll@GETpublic Response getEmployees(@Auth User user) {return Response.ok(EmployeeDB.getEmployees()).build();}
2)用户必须经过验证。 仅角色为ADMIN的所有用户都可以使用 API。
@RolesAllowed({ "ADMIN" })@GET@Path("/{id}")public Response getEmployeeById(@PathParam("id") Integer id, @Auth User user) {Employee employee = EmployeeDB.getEmployee(id);if (employee != null)return Response.ok(employee).build();elsereturn Response.status(Status.NOT_FOUND).build();}
这样,您可以根据需要在所有 API 中添加各种认证方案。
测试 Dropwizard 基本验证代码
让我们测试一下我们的安全 API。
调用任何安全的 API

基本认证屏幕
http://localhost:8080/employees

经过认证并允许所有角色
http://localhost:8080/employees/1

经过认证并仅允许ADMIN角色
将我的问题放在评论部分。
学习愉快!
