站内账户绑定的介绍和实现

在上一节说过绑定的一种实现,就是用第三方进行授权绑定,从而实现用户信息的共享。然后本节中将阐述另外一种全新的绑定方案 ——— 站内绑定。

在同一个网站下,两个用户建立绑定关系,并且授权对方能够查看的信息范围。或许你会有此疑问:既然在同一网站之下,就应该可以加为好友关系,并且能够获取对方的用户信息,为何需要绑定,这样的绑定能够获取除好友关系之外的哪些权限?

首先,同一网站下的用户,的确可以搜索到,并且可以加为好友关系,不过这种关系只是信息共享的低级部分,你只能查看到对方授权公开的信息,除此之外你一无所获。

站内用户绑定,就是不仅仅实现信息共享的,是为两个在现实中有紧密联系的用户建立的一套信息互助系统,这种绑定是单向关系,并且这种绑定实际授权的不仅仅是信息,也是给予对方操作自己的权限,归根结底,这种绑定其实就权限管理 , 但是这种权限管理与网站的权限管理有很大不同。

  • 网站权限管理是以系统为中心,用户拥有的权限都是对系统而言的 , 是一套权限集;

  • 而站内绑定的权限管理其实是以用户为中心的,每一个用户都是一套权限管理系统,并且拥有一套以自己为中心的权限集,管理着其他用户操作自己的权限。(当然每个用户依然拥有系统的权限)

比如:

秘书(A) 申请绑定 老板(B) , 老板 同意绑定并且授权 秘书 可以对他的日程进行编辑,那么 秘书 就可以进入 老板 的日程,并且拥有新增编辑的功能;

这种绑定关系就是将同一系统中的两个用户建立起绑定关系,被绑定者可以授权绑定者一定的权限进行操作,除了以上的例子之外,可能还有 老师学生 的绑定, 家长孩子 的绑定等等。

绑定的步骤:

  • 用户A 申请绑定 用户B ;
  • 用户B 可以同意绑定、拒绝绑定或者忽略,如何B同意绑定,进而选择授权绑定者的权限;
  • 用户A 绑定成功, 就可以操作B给予他的操作权限;

以上的绑定,其实就让A 能够 以B的身份去拿用户B的数据。

下面将简单说一下绑定用户数据互通的实现过程。

构建用户代理类

用户对象中包含了绑定的用户或组织信息,当进入到绑定用户后,对被绑定者的任何授权操作都相当于被绑定者自己在操作。

public class UserProxy implements MethodInterceptor {

    private User  target;
    private Session currentSessoin;
    private Object proxy;

    public Object getProxy() {
        return this.proxy;
    }

    /** 
     * 创建代理对象 
     *  
     * @param target 
     * @return 
     */  
    public Object getInstance(User target, Session userSession) {

        //1
        this.target         = target;
        this.currentSessoin = userSession;

        //2
        Enhancer enhancer = new Enhancer();  
        enhancer.setSuperclass(this.target.getClass());

        //3 回调方法  
        enhancer.setCallback(this);

        proxy = enhancer.create();
        //4 创建代理对象  
        return proxy;
    }

}

设置用户代理类的方法劫持,将对A用户的访问转移到对B用户的访问中,从而实现用户之间的单向数据操作。

@Override
   public Object intercept(Object arg0, Method arg1, Object[] arg2,
           MethodProxy arg3) throws Throwable {

       if (currentSessoin.getBindingDomain() != null) {
           // ..省略获取权限,如果有权限进行以下
           if (arg1.getName().equals("getDomain")) {
               return currentSessoin.getBindingDomain();
           } 
       } else if (currentSessoin.getBindingUser() != null) {
           // ..省略获取权限,如果有权限进行以下
           return arg1.invoke(currentSessoin.getBindingUser(), arg2);
       }
       return arg1.invoke(this.target, arg2);
   }    

定义Session

一个session就是一次会话

public class Session {

    private String sessionID;

    private User loginUser;         // 登录用户

    private Domain bindingDomain;    // 绑定的组织

    private User   bindingUser;        // 绑定的用户

}

Session与用户代理绑定

系统中每一个用户登录成功之后,都会生成一个相应的用户代理类与Session绑定,并且设置有失效的时间,超过失效时间或者用户主动退出后,Session和用户代理类就无效了。

public class SessionManagerImp implements SessionManager, InactiveSessionOperation {

    /**
     * 缓存Session
     */
    private Map<String, Session> cache = new HashMap<String, Session>();

    private ReadWriteLock lock = new ReentrantReadWriteLock();

    /**
     * 扫描不活动的Session
     */
    private Timer scanTimer = new Timer();

    /**
     * 每次扫描的时间间隔,毫秒
     */
    private static final int SCANINTERVAL = 300000;

    /**
     * 失效的Session时间间隔
     */
    private static final int INACTIVEINTERVAL = 4 * SCANINTERVAL;

    @Override
    public Session openNewSession(User aUser, int resource) {

        Session sess = new Session(Session.generateSessionID(), null, Calendar.getInstance(), resource);

        //1
        User userPr = (User)(new UserProxy().getInstance(aUser, sess));

        //2
        sess.setLoginUser(userPr);
        sess.setTrueUser(aUser);

        try {
            this.lock.writeLock().lock();
            cache.put(sess.getSessionID(), sess);

        } finally {
            this.lock.writeLock().unlock();
        }

        return sess;
    }
}

只要设置了用户代理类的bindUser , 对bindUser的任何操作就相当于bindUser自己去操作,当然这里还有更进一步的权限管理,在用bindUser去操作之前,需要先获取bindUser给当前用户的权限是哪些,如果这个操作并未授权,当前用户也无法调用。这里介绍的是绑定之后,绑定者 如何 获取 被绑定者的数据,并等同于被绑定者进行操作。

这里没有介绍的如何进行绑定,这种授权方案从安全角度可以参考当下比较流行的OAuth协议(就像第三方授权登录一样),这一部分内容有很多资料,这里不做介绍。

本站总访问量