一个简单shiro案例
@Component
public class SimpleService {
private static Logger log = LoggerFactory.getLogger(SimpleService.class);
@RequiresPermissions("write")
public void writeRestrictedCall() {
log.info("executing method that requires the 'write' permission");
}
@RequiresPermissions("read")
public void readRestrictedCall() {
log.info("executing method that requires the 'read' permission");
}
}
@Component
public class QuickStart {
private static Logger log = LoggerFactory.getLogger(QuickStart.class);
@Autowired
private SecurityManager securityManager;
@Autowired
private SimpleService simpleService;
public void run() {
// get the current subject
Subject subject = SecurityUtils.getSubject();
// Subject is not authenticated yet
Assert.isTrue(!subject.isAuthenticated());
// login the subject with a username / password
UsernamePasswordToken token = new UsernamePasswordToken("joe.coder", "password");
subject.login(token);
// joe.coder has the "user" role
subject.checkRole("user");
// joe.coder does NOT have the admin role
Assert.isTrue(!subject.hasRole("admin"));
// joe.coder has the "read" permission
subject.checkPermission("read");
// current user is allowed to execute this method.
simpleService.readRestrictedCall();
try {
// but not this one!
simpleService.writeRestrictedCall();
}
catch (AuthorizationException e) {
log.info("Subject was NOT allowed to execute method 'writeRestrictedCall'");
}
// logout
subject.logout();
Assert.isTrue(!subject.isAuthenticated());
}
/**
* Sets the static instance of SecurityManager. This is NOT needed for web applications.
*/
@PostConstruct
private void initStaticSecurityManager() {
SecurityUtils.setSecurityManager(securityManager);
}
}
运行结果:
Connected to the target VM, address: ‘127.0.0.1:8304’, transport: ‘socket’
2019-08-20 23:12:10,976 INFO [org.apache.shiro.session.mgt.AbstractValidatingSessionManager] - Enabling session validation scheduler…
Disconnected from the target VM, address: ‘127.0.0.1:8304’, transport: ‘socket’
2019-08-20 23:12:11,257 INFO [org.apache.shiro.samples.spring.SimpleService] - executing method that requires the ‘read’ permission
2019-08-20 23:12:11,258 INFO [org.apache.shiro.samples.spring.QuickStart] - Subject was NOT allowed to execute method ‘writeRestrictedCall’
- shiro会向容器中注册自动代理创建器,以及增强器。
@Bean
@DependsOn("lifecycleBeanPostProcessor")
protected DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
return super.defaultAdvisorAutoProxyCreator();
}
@Bean
protected AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
return super.authorizationAttributeSourceAdvisor(securityManager);
}
StaticMethodMatcherPointcutAdvisor 既是增强器,也是切点。
UML组件基本介绍:
- PointcutAdvisor 帮忙获取Pointcut,获取通知Advice (AopUtils 277-279)
- Pointcut 帮助找到MethodMatcher (AopUtils 224行)
- MethodMatcher 决定当前类的实例是否需要自动代理 (AopUtils 243行)
- Advice 本质上就是MethodInterceptors(复数)方法拦截器数组
//StaticMethodMatcherPointcutAdvisor 重写了MethodMatcher方法,当spring获取到所有的Advisor增强器
//后,会判断当前这个类,是否需要应用代理。A
public boolean matches(Method method, Class targetClass) {
Method m = method;
if ( isAuthzAnnotationPresent(m) ) {
return true;
}
//The 'method' parameter could be from an interface that doesn't have the annotation.
//Check to see if the implementation has it.
if ( targetClass != null) {
try {
m = targetClass.getMethod(m.getName(), m.getParameterTypes());
return isAuthzAnnotationPresent(m) || isAuthzAnnotationPresent(targetClass);
} catch (NoSuchMethodException ignored) {
//default return value is false. If we can't find the method, then obviously
//there is no annotation, so just use the default return value.
}
}
return false;
}
AopUtils 242行体现
如果在方法上标有这些注解,那么则创建代理对象。
@ RequiresPermissions,@RequiresRoles.class,
@RequiresUser.,@ RequiresGuest.@RequiresAuthentication