1. Custom Subject Instances
Shiro在1.0版本添加了一个新的特性,用于在特殊情景自定义subject。
2. Subject.Builder
Subject.Builder可以创建一个匿名,无session关联的Subject实例:
默认无参的Subject.Builder将使用应用中存在的SecurityManager。也可以指定 SecurityManager:
Subject.Builder提供的其他方法都需要在buildSubject方法之前调用,假设有一个session ID,你想设置到Subject的session上:
或者想设置Subject的标识信息:
然后就可以使用Subject。需要注意的是,这样方式创建的Subject不会自动与应用线程绑定。如果想随处调用SecurityUtils.getSubject(),必须保证Subject与线程已绑定。
3. Thread Association(线程关联)
与线程绑定有三种方式:
1. Automatic Association -- 通过Subject.execute方法执行Callable或Runnable。
2. Manual Association -- 手动绑定或解除。
3. Different Thread -- 通过Subject.associateWith方法将Subject与Callable或Runnable绑定,并使用其他线程执行Callable或Runnable。
3.1 Automatic Association(自动关联)
如果想让Subject与线程暂时性绑定,可以直接通过Subject的execute方法执行Callable或Runnable,线程执行完毕,就解除绑定。
假如在应用启动时,有一些操作需要执行,当执行完后,希望Subject可以回到自动绑定到线程的环境下,可以这样做:
也支持Callable:
这在框架开发中很有用。比如,Shiro支持Spring的远程调用,这可以保证远程调用被执行:
3.2 Manual Association(手动关联)
在某些场景下,比如说使用Shiro进行框架级的集成开发时,就可能需要手动管理ThreadState(Shiro中保证Subject可以在线程执行间随处可用)。需要注意的是,要保证线程执行完后,清除ThreadState:
3.3 A Different Thread(使用其他线程方式)
Subject.associateWith方法将Subject与Callable或Runnable绑定,在线程执行期间,Subject被挂起,直到线程执行完后,Subject才可用, Callable例子:
使用Runnable的例子:
Shiro在1.0版本添加了一个新的特性,用于在特殊情景自定义subject。
2. Subject.Builder
Subject.Builder可以创建一个匿名,无session关联的Subject实例:
Subject subject = new Subject.Builder().buildSubject()
默认无参的Subject.Builder将使用应用中存在的SecurityManager。也可以指定 SecurityManager:
SecurityManager securityManager = //acquired from somewhere
Subject subject = new Subject.Builder(securityManager).buildSubject();
Subject.Builder提供的其他方法都需要在buildSubject方法之前调用,假设有一个session ID,你想设置到Subject的session上:
Serializable sessionId = //acquired from somewhere
Subject subject = new Subject.Builder().sessionId(sessionId).buildSubject();
或者想设置Subject的标识信息:
Object userIdentity = //a long ID or String username, or whatever the "myRealm" requires
String realmName = "myRealm";
PrincipalCollection principals = new SimplePrincipalCollection(userIdentity, realmName);
Subject subject = new Subject.Builder().principals(principals).buildSubject();
然后就可以使用Subject。需要注意的是,这样方式创建的Subject不会自动与应用线程绑定。如果想随处调用SecurityUtils.getSubject(),必须保证Subject与线程已绑定。
3. Thread Association(线程关联)
与线程绑定有三种方式:
1. Automatic Association -- 通过Subject.execute方法执行Callable或Runnable。
2. Manual Association -- 手动绑定或解除。
3. Different Thread -- 通过Subject.associateWith方法将Subject与Callable或Runnable绑定,并使用其他线程执行Callable或Runnable。
3.1 Automatic Association(自动关联)
如果想让Subject与线程暂时性绑定,可以直接通过Subject的execute方法执行Callable或Runnable,线程执行完毕,就解除绑定。
假如在应用启动时,有一些操作需要执行,当执行完后,希望Subject可以回到自动绑定到线程的环境下,可以这样做:
Subject subject = //build or acquire subject
subject.execute( new Runnable() {
public void run() {
//subject is 'bound' to the current thread now
//any SecurityUtils.getSubject() calls in any
//code called from here will work
}
});
//At this point, the Subject is no longer associated
//with the current thread and everything is as it was before
也支持Callable:
Subject subject = //build or acquire subject
MyResult result = subject.execute( new Callable<MyResult>() {
public MyResult call() throws Exception {
//subject is 'bound' to the current thread now
//any SecurityUtils.getSubject() calls in any
//code called from here will work
...
//finish logic as this Subject
...
return myResult;
}
});
//At this point, the Subject is no longer associated
//with the current thread and everything is as it was before
这在框架开发中很有用。比如,Shiro支持Spring的远程调用,这可以保证远程调用被执行:
Subject.Builder builder = new Subject.Builder();
//populate the builder's attributes based on the incoming RemoteInvocation
...
Subject subject = builder.buildSubject();
return subject.execute(new Callable() {
public Object call() throws Exception {
return invoke(invocation, targetObject);
}
});
3.2 Manual Association(手动关联)
在某些场景下,比如说使用Shiro进行框架级的集成开发时,就可能需要手动管理ThreadState(Shiro中保证Subject可以在线程执行间随处可用)。需要注意的是,要保证线程执行完后,清除ThreadState:
Subject subject = new Subject.Builder()...
ThreadState threadState = new SubjectThreadState(subject);
threadState.bind();
try {
//execute work as the built Subject
} finally {
//ensure any state is cleaned so the thread won't be
//corrupt in a reusable or pooled thread environment
threadState.clear();
}
3.3 A Different Thread(使用其他线程方式)
Subject.associateWith方法将Subject与Callable或Runnable绑定,在线程执行期间,Subject被挂起,直到线程执行完后,Subject才可用, Callable例子:
Subject subject = new Subject.Builder()...
Callable work = //build/acquire a Callable instance.
//associate the work with the built subject so SecurityUtils.getSubject() calls works properly:
work = subject.associateWith(work);
ExecutorService executorService = new java.util.concurrent.Executors.newCachedThreadPool();
//execute the work on a different thread as the built Subject:
executor.execute(work);
使用Runnable的例子:
Subject subject = new Subject.Builder()...
Runnable work = //build/acquire a Runnable instance.
//associate the work with the built subject so SecurityUtils.getSubject() calls works properly:
work = subject.associateWith(work);
Executor executor = new java.util.concurrent.Executors.newCachedThreadPool();
//execute the work on a different thread as the built Subject:
executor.execute(work);