Integrating Deadbolt

[未完成,三日内完成]
实现be.objectify.deadbolt.java.DeadboltHandler接口用于提供Deadbolt满足你的项目权限约束。这个接口有四个主要的方法:
getSubject 从缓存或者数据库中获取当前用户
beforeAuthCheck 运行一个可以阻塞将来执行的授权前(pre-authorization)任务
onAuthFailure 定义当授权失败后的行为
getDynamicResourceHandler 为动态约束类型提供一个钩子
如果你选择为roles关联permission,你应该实现getPermissionsForRole方法。这使得分配permission非常容易,在subject被分配一个角色,并且被 RoleBasedPermissions 约束的情况下。RoleBasedPermissions请求subject,至少拥有一项permission。这项permission至少符合getPermissionsForRole中获取到的一项权限。这个方法的默认实现返回一个包含空列表的completed future。

授权成功

如果你想要知道何时授权成功,那么实现onAuthSuccess(Http.Context context, String constraintType, ConstraintPoint constraintPoint)方法。每当约束允许一个操作进行时,该方法被执行。
context can be used to determine request-specific information
constraintType is the name of the constraint, e.g. Dynamic, SubjectPresent, etc
constraintPoint indicates where the constraint was applied. Constraints applied using annotations (ConstraintPoint.CONTROLLER) and the routes (ConstraintPoint.FILTER) only occur once per request, but it’s possible for multiple authorizations to occur when using template constraints (ConstraintPoint.TEMPLATE). Using constraintPoint to differentiate can improve the performance of your implementation.

Dynamic constraint support

You only need to implement be.objectify.deadbolt.java.DynamicResourceHandler if you’re planning to use Dynamic or Pattern.CUSTOM constraints. Dynamic constraints are tests implemented entirely by your code. This interface has two functions:

isAllowed is used by the Dynamic constraint
checkPermission is used by the Pattern constraint when the pattern type is CUSTOM

Exposing the handler(s)

In order to expose your handler (or handlers - you can have more than one) to Deadbolt, you will need to implement the be.objectify.deadbolt.java.cache.HandlerCache trait. This implementation needs to

Provide a default handler; you can always use a specific handler in a template or controller, but if nothing is specified a well-known instance will be used.
Provide a named instance
The simplest possible implementation of HandlerCache only supports one DeadboltHandler, in which case both get and apply always return the same instance.

A one-handler cache example
 @Singleton
public class MySimpleHandlerCache implements HandlerCache
{
    private final DeadboltHandler defaultHandler = new MyDeadboltHandler();

    @Override
    public DeadboltHandler apply(final String key)
    {
        return defaultHandler;
    }

    @Override
    public DeadboltHandler get()
    {
        return defaultHandler;
    }
}

If you need to support multiple handlers, you will need some internal mechanism for differentiating between them based on the key parameter of the apply method..

An example HandlerCache implementation
 @Singleton
public class MyHandlerCache implements HandlerCache
{
    private final DeadboltHandler defaultHandler = new MyDeadboltHandler();
    private final Map<String, DeadboltHandler> handlers = new HashMap<>();

    public MyHandlerCache()
    {
        handlers.put(HandlerKeys.DEFAULT.key, defaultHandler);
        handlers.put(HandlerKeys.ALT.key, new MyAlternativeDeadboltHandler());
    }

    @Override
    public DeadboltHandler apply(final String key)
    {
        return handlers.get(key);
    }

    @Override
    public DeadboltHandler get()
    {
        return defaultHandler;
    }
}

HandlerKeys, in the above example, is just a class declaring constants that standardize handler names; because you can define specific handlers on a per-constraint basis, it makes sense to define them in a well-known place.

Note the use of ConfigKeys.DEFAULT_HANDLER_KEY - this is the default handler key specified by all annotations. In previous versions of Deadbolt, annotation-driven constraints would use HandlerCache#apply(DEFAULT_HANDLER_KEY) to obtain the handler and so the default handler had to be associated with DEFAULT_HANDLER_KEY. As of Deadbolt 2.5.3, this has been improved and any annotation-driven constraint using the default handler key will instead use HandlerCache#get.

Handler names
 import be.objectify.deadbolt.java.ConfigKeys;

public class HandlerNames {

    public static final String DEFAULT = ConfigKeys.DEFAULT_HANDLER_KEY;
    public static final String ALT = "alt-handler";

    private HandlerNames() {}
}

Finally, expose your handlers to Deadbolt. To do this, you will need to create a small module that binds your handler cache by type…

Binding the HandlerCache implementation
 package com.example.modules

import be.objectify.deadbolt.java.cache.HandlerCache;
import play.api.Configuration;
import play.api.Environment;
import play.api.inject.Binding;
import play.api.inject.Module;
import scala.collection.Seq;
import security.MyHandlerCache;

import javax.inject.Singleton;

public class CustomDeadboltHook extends Module
{
    @Override
    public Seq<Binding<?>> bindings(final Environment environment,
                                    final Configuration configuration)
    {
        return seq(bind(HandlerCache.class).to(MyHandlerCache.class).in(Singleton.class));
    }
}

…and add it to your application.conf.

conf/application.conf
play {
    modules {
        enabled += be.objectify.deadbolt.scala.DeadboltModule
        enabled += com.example.modules.CustomDeadboltHook
    }
}

Injecting handlers into the HandlerCache

In the example handler cache above, the DeadboltHandler instance is created directly within the object. What happens if you want to inject it? Just use the existing dependency injection mechanism.

Binding the DeadboltHandler implementation
 public class CustomDeadboltHook extends Module
{
    @Override
    public Seq<Binding<?>> bindings(final Environment environment,
                                    final Configuration configuration)
    {
        return seq(bind(DeadboltHandler.class).to(MyDeadboltHandler.class).in(Singleton.class),
                   bind(HandlerCache.class).to(MyHandlerCache.class).in(Singleton.class));
    }
}

Your handler cache can now be injected with that instance.

Mapping the injected DeadboltHandler implementation
 @Singleton
public class MyHandlerCache implements HandlerCache
{
    private final DeadboltHandler defaultHandler;
    private final Map<String, DeadboltHandler> handlers = new HashMap<>();

    @Inject
    public MyHandlerCache(final DeadboltHandler handler)
    {
        this.defaultHandler = handler;
        handlers.put(HandlerKeys.DEFAULT.key, defaultHandler);
        handlers.put(HandlerKeys.ALT.key, new MyAlternativeDeadboltHandler());
    }

    // ...
}

But, what happens if you want to have multiple handlers defined and injected? The most flexible mechanism is to qualify the bindings through the use of custom annotations. For the following example, we will have two handler implementations; scaling up to more handlers just follows the same logical process.

This example uses Guice, which is the default DI framework of Play; if you’re using a different DI framework, you will need to check how it supports multiple bindings of an interface.

First, create one annotation per handler implementation. These annotations will be annotated with com.google.inject.BindingAnnotation.

Binding qualifiers
 import com.google.inject.BindingAnnotation;

import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

public class HandlerQualifiers
{
    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.PARAMETER})
    @BindingAnnotation
    public @interface MainHandler
    {
    }

    @Retention(RetentionPolicy.RUNTIME)
    @Target({ElementType.TYPE, ElementType.PARAMETER})
    @BindingAnnotation
    public @interface SomeOtherHandler
    {
    }
}

You can now use these annotations on their respective handlers.

Qualify the DeadboltHandler implementation
 @HandlerQualifiers.MainHandler
public class MyDeadboltHandler extends AbstractDeadboltHandler

Create a constructor in your handler cache which accepts the handlers. The parameters use the same annotations to identify which instance will be passed as an argument for that parameter.

Qualify the injected handlers
 public class MyHandlerCache implements HandlerCache
{
    private final DeadboltHandler handler;

    private final Map<String, DeadboltHandler> handlers = new HashMap<>();

    @Inject
    public MyHandlerCache(@HandlerQualifiers.MainHandler final DeadboltHandler handler,
                          @HandlerQualifiers.SomeOtherHandler final DeadboltHandler otherHandler)
    {
        this.handler = handler;
        this.handlers.put(handler.handlerName(),
                          handler);
        this.handlers.put(otherHandler.handlerName(),
                          otherHandler);
    }

    @Override
    public DeadboltHandler apply(final String name)
    {
        return handlers.get(name);
    }

    @Override
    public DeadboltHandler get()
    {
        return handler;
    }
}

The final step is to update your bindings to use the qualifiers.

Qualify the bindings
 public class CustomDeadboltHook extends Module
{
    @Override
    public Seq<Binding<?>> bindings(final Environment environment,
                                    final Configuration configuration)
    {
        return seq(bind(DeadboltHandler.class).qualifiedWith(HandlerQualifiers.MainHandler.class).to(MyDeadboltHandler.class).in(Singleton.class),
                   bind(DeadboltHandler.class).qualifiedWith(HandlerQualifiers.SomeOtherHandler.class).to(SomeOtherDeadboltHandler.class).in(Singleton.class),
                   bind(HandlerCache.class).to(MyHandlerCache.class).in(Singleton.class));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值