shiro的url配置采用第一次匹配优先的原则,则从上往下匹配
DelegatingFilterProxy类存在与spring-web包中,其作用就是一个filter的代理,用这个类的好处是可以通过spring容器来管理filter的生命周期,还有就是,可以通过spring注入的形式,来代理一个filter执行,如shiro。
shiroFilter
org.springframework.web.filter.DelegatingFilterProxy
targetFilterLifecycle
true
targetBeanName
shiroFilter1
初始化时,自动调用init方法。
Shiro认证思路。
//Handler类
@Controller
@RequestMapping("/shiro")
public class ShiroHandle {
@RequestMapping("/login")
public String login(@RequestParam("username")String username,@RequestParam("password")String password){
Subject currentUser = SecurityUtils.getSubject();
if (!currentUser.isAuthenticated()) {
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
System.out.println(token.hashCode());
token.setRememberMe(true);
try {
currentUser.login(token);
}
catch (AuthenticationException ae) {
ae.printStackTrace();
}
}
return "";
}
}
//shiroRealm类
public class ShiroRealm extends AuthenticatingRealm {
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("doAuthentication"+token.hashCode());
return null;
}
}
Handler类中执行的login方法传入的token值会被传到shiroRealm类里面。两个token实为同一个对象。
Shiro密码的比对是由 AuthenticatingRealm 类的assertCredentialsMatch方法使用CredentialsMatcher来进行比对的。
shiro默认的认证策略是AllLeastOneSuccessfulStrategy。
若需要实现多realm认证的话,需要在spring中注册ModularRealmAuthenticator类,并且作为参数赋给securityManager。
但在实际生产中,我们是从securityManager读取realm的,所以把realms从securityManager注入。那为什么可以这样做呢?是因为在securityManager初始化的时候,会判断authenticator属性对象是否属于ModularRealmAuthenticator类,如果是,会将自身realms属性赋予authenticator属性对象。
AuthenticatingRealm-------->若只需要认证的话,只继承AuthenticatingRealm就可
AuthorizingRealm--------->用于授权和认证的realm一般使用这个
AuthorizingRealm继承于AuthenticatingRealm但是没有实现父类的doGetAuthenticationInfo方法
若为多realm授权认证的话,shiro会调用ModularRealmAuthorizer类来进行认证(从源码中可以看到,只要有一个Realm通过就返回true),但是实际进行授权认证的还是AuthorizingRealm,因为在源码374行中调用的hasRole方法会继续调用AuthorizingRealm授权认证。
sessionDao可以讲session进行序列号并存到数据库中,进行增删改查。在单机应用中,作用可以是在service层也可以通过shiro拿到session。而在集群分布式中作用就会比较大,共享session很有必要,因为当同一个用户发起请求时,可能被调度到不同的机器上访问(负载均衡),这时就可能同一个用户的求情会被当成是多个用户的请求,session共享就很有必要了。
2.为什么shiro的注解一般都加在control层,而不是在service层。
因为一般在项目中我们会在service层会加上@Transactional 事务注解,这个时候service层对象已经是个代理对象了,在加上shiro权限注解的话,代理的代理,会在注入的时候发生异常。