在上一节说过绑定的一种实现,就是用第三方进行授权绑定,从而实现用户信息的共享。然后本节中将阐述另外一种全新的绑定方案 ——— 站内绑定。
在同一个网站下,两个用户建立绑定关系,并且授权对方能够查看的信息范围。或许你会有此疑问:既然在同一网站之下,就应该可以加为好友关系,并且能够获取对方的用户信息,为何需要绑定,这样的绑定能够获取除好友关系之外的哪些权限?
首先,同一网站下的用户,的确可以搜索到,并且可以加为好友关系,不过这种关系只是信息共享的低级部分,你只能查看到对方授权公开的信息,除此之外你一无所获。
站内用户绑定,就是不仅仅实现信息共享的,是为两个在现实中有紧密联系的用户建立的一套信息互助系统,这种绑定是单向关系,并且这种绑定实际授权的不仅仅是信息,也是给予对方操作自己的权限,归根结底,这种绑定其实就权限管理 , 但是这种权限管理与网站的权限管理有很大不同。
网站权限管理是以系统为中心,用户拥有的权限都是对系统而言的 , 是一套权限集;
而站内绑定的权限管理其实是以用户为中心的,每一个用户都是一套权限管理系统,并且拥有一套以自己为中心的权限集,管理着其他用户操作自己的权限。(当然每个用户依然拥有系统的权限)
比如:
秘书(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协议(就像第三方授权登录一样),这一部分内容有很多资料,这里不做介绍。