我有一个HTTP安全API,可以像这样配置安全性,身份验证和授权
SecurityConfigurationBuilder configurationBuilder = new SecurityConfigurationBuilder();
HttpSecurityBuilder builder = configurationBuilder.http();
builder
.pathGroup("REST Service Group A") //returns PathConfigurationBuilder
.inbound() //returns InboundConfigurationBuilder
.authc() //returns AuthenticationConfigurationBuilder
.form() //returns FormAuthenticationConfigurationBuilder
.loginPage("/loginA.html")
.errorPage("/errorA.html")
.authz()
.allowedRoles("Role A")
.pathGroup("REST Service Group B")
.inbound()
.authc()
.form()
.loginPage("/loginB.html")
.errorPage("/errorB.html")
.authz() //returns AuthorizationConfigurationBuilder
.allowedRoles("Role B")
.path("/rest/a/*", "REST Service Group A") //returns PathConfigurationBuilder
.path("/rest/b/*", "REST Service Group B");
HttpSecurityConfiguration configuration = builder.build().getHttpSecurityConfiguration();
注意:每个config方法都返回一个类的对象。我只提到了其中的几个。
同样,我们也可以这样配置,
SecurityConfigurationBuilder configurationBuilder = new SecurityConfigurationBuilder();
HttpSecurityBuilder builder = configurationBuilder.http();
builder
.allPaths()
.inbound()
.authc()
.form()
.loginPage("/login.html")
.errorPage("/error.html")
.authz()
.allowedRoles("Role A", "Role B")
.allowedGroups("Group A", "Group B")
.allowedRealms("Realm A", "Realm B")
.expression("#{identity.isLoggedIn()}");
HttpSecurityConfiguration configuration = builder.build().getHttpSecurityConfiguration();
我现在需要在枚举字段上使用注释提供类似的配置。例如。
//Declaration of @annotation_A depends on @annotation_B means that annotation_B can only be declared if annotation_A is declared.
//Also, declaration of annotation_A must precede annotation_B
@PicketlinkHttpSecurity
public interface Security {
static enum Secure {
//optional
@Http
//Any one of these,optional
@Permissive
@Restrictive
//Any one of these, optional
@AllPaths
@Path(pathName = "Path URL Pattern")
@Path(pathName = "Path URL Pattern", pathGroup = "Path Group")
@PathGroup(pathGroup = "Path Group")
//optional, declaration depends on (@allPaths, @path, @pathGroup) whichever is declared
@Logout
//optional, declaration depends on (@allPaths, @path, @pathGroup) whichever is declared
@Inbound
//optional, declarion depends on @inbound
@Methods(methods = {"method_one", "method_two"}, ...)
//optional, declaration depends on @inbound
@Headers(headerName = "name", headerValues={"value1", "value2", ...}, requestedWith = "request_header")
//optional, declaration depends on (@allPaths, @path, @pathGroup) whichever is delclared
@Outbound
//optional, declaration depends on @outbound
@RedirectTo(redirect = "redirectPath")
//optional, declaration depends on @inbound/@outbound
@Authc
//Any one of form,basic,digest,x509,token(//optional and declaration depends on @authc)
@Form(restoreOriginalRequest = "yes_OR_no", loginPage="loginPage", errorPage="errorPage")
@Basic(realmName="realmName")
@Digest(realmName="realmName")
@X509(subjectRegex="")
@Token
//optional, declaration depends on @inbound/@outbound
@Authz
//optional, any one or many of these, declaration depends on @authz
@AllowedRoles(Roles={"Role_A", "Role_B", ...})
@AllowedGroups(Goups={"Goup_A", "Goup_B", ...})
@AllowedRealms(Realms={"Realm_A", "Realm_B", ...})
@Expressions(expressions= {"expression1", "expression2", ...})
SecurityConfigiration_One,
//Other Security Configuration Annotations Decorated Enum Fields
}
}
现在,我有一个类SecurityConfigExtension,它试图读取这个枚举类并构建SecurityConfigurationBuilder。 此类中的不完整代码是
public class SecurityConfigExtension implements Extension {
private transient final Logger log = Logger.getLogger(SecurityConfigExtension.class);
SecurityConfigurationBuilder builder = new SecurityConfigurationBuilder();
HttpSecurityBuilder httpSecurityBuilder = new HttpSecurityBuilder(builder);
PathConfigurationBuilder pathConfigurationBuilder;
public <T> void processAnnotatedType(@Observes ProcessAnnotatedType<T> event) {
AnnotatedType<T> tp = event.getAnnotatedType();
if (tp.isAnnotationPresent(PicketlinkHttpSecurity.class)) {
if (!tp.getJavaClass().isInterface()) {
log.warn("ViewConfig annotation should only be applied to interfaces, and [" + tp.getJavaClass()
+ "] is not an interface.");
} else {
for (Class<?> clazz : tp.getJavaClass().getClasses()) {
for (Field enumm : clazz.getFields()) {
for (Annotation a : enumm.getAnnotations()) {
if (a.annotationType() == Http.class) {
this.httpSecurityBuilder = this.builder.http();
} else if (a.annotationType() == Permissive.class) {
this.httpSecurityBuilder = this.httpSecurityBuilder.permissive();
} else if (a.annotationType() == Restrictive.class) {
this.httpSecurityBuilder = this.httpSecurityBuilder.restrictive();
} else if (a.annotationType() == AllPaths.class) {
this.pathConfigurationBuilder = this.httpSecurityBuilder.allPaths();
} else if (a.annotationType() == Path.class) {
Path path = (Path) a;
String pathName = path.pathName();
String pathGroup = path.pathGroup();
if (pathName != null && !pathName.isEmpty() && pathGroup != null && !pathGroup.isEmpty()) {
this.pathConfigurationBuilder = this.httpSecurityBuilder.path(pathName, pathGroup);
} else {
this.pathConfigurationBuilder = this.httpSecurityBuilder.path(pathName);
}
}
}
}
}
}
}
}
}
我的问题是构建类似于上述插图的配置的最佳方式。我使用反射来读取传递给注释的参数的值。但是根据当前的代码,它看起来非常沉重和糟糕,因为在应用配置之后,我必须使用与返回对象相同类型的对象来初始化它,因此,可以应用下一个配置并继续该过程。 >有没有更好的方法 ??