为HTTP Security API提供基于注释的配置?

时间:2014-08-16 10:50:47

标签: java reflection configuration enums annotations

我有一个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);
                            }
                        }
                    }
                }
            }
        }
     }
  }
}

我的问题是构建类似于上述插图的配置的最佳方式。我使用反射来读取传递给注释的参数的值。但是根据当前的代码,它看起来非常沉重和糟糕,因为在应用配置之后,我必须使用与返回对象相同类型的对象来初始化它,因此,可以应用下一个配置并继续该过程。 >有没有更好的方法 ??

0 个答案:

没有答案