最近在学习shiro的框架,首先先学一些理论知识
简介
Apache shiro是一个安全框架,功能可能没spring security强大,但是小而简单。
首先流程
Subject:应用层的直接交互对象是subject,代表当前的用户,所有的subject都绑定到securitymanager上。
Securitymanager:安全管理器,管理着所有的subject,相当于struts2中的filterDispatcher;是shiro的心脏,负责进行认证授权,会话缓存的管理。
Authenticator:认证器,负责认证的。是一个扩展点,如果觉得shiro默认的不好,可以自定义。但是要认证策略(authentication strategy)即啥情况下算认证通过。
Authrizer:授权器,即访问控制器,用来决定主体是否有权限进行相应的操作,即控制着用户能访问应用中心的哪些功能。
Realm。域shiro从realm中获取安全数据(角色,权限,用户).securitymanager需要验证用户身份时,需要从realm中获取相应的用户进行身份比较。可以看做DataSource。可以有1个或者多个,可以认为是安全实体数据库。一般需要自己实现。
SessionManager:管理session,可以实现单点登录。
SessionDAO:数据访问对象,用于回话的CRUD,比如把session存到数据库或者缓存。另外sessionDAO可以使用Cache进行缓存,以提高性能。
CacheManager:缓存控制器,来管理用户,角色,权限等的缓存。
Cryptography:密码模块,用于密码加解密。
身份验证
@Test
public void testCustomRealm() {
//1、获取SecurityManager工厂,此处使用Ini配置文件初始化SecurityManager
Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro-realm.ini");
//2、得到SecurityManager实例 并绑定给SecurityUtils
SecurityManager securityManager = factory.getInstance();
SecurityUtils.setSecurityManager(securityManager);
//3、得到Subject及创建用户名/密码身份验证Token(即用户身份/凭证)
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken("zhang", "123");
try {
//4、登录,即身份验证
subject.login(token);
} catch (AuthenticationException e) {
//5、身份验证失败
e.printStackTrace();
}
Assert.assertEquals(true, subject.isAuthenticated());
//6、退出
subject.logout();
}
public class MyRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection arg0) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authcToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authcToken;
String username = token.getUsername();
String password = String.valueOf(token.getPassword());
if(!"zhang".equals(username)) {
System.out.println("用户名错误");
}
if(!"123".equals(password)) {
System.out.println("密码错误");
}
System.out.println("hahaha");
return new SimpleAuthenticationInfo(username, password,getName());
}
}
shiro-realm.ini
[main]
MyRealm = shirotest.com.shiro.MyRealm
securityManager.realms=$MyRealm
流程:
Subject.login(token)进行登录将其委托给securitymanager,然后委托给Authenticator进行身份验证,然后Authenticator把相应的token传给realm。
授权
首先调用subject.ispermitter /hasRole接口,securityManager委托给authenticator 通过permissionResolve把字符串转化为permission实例。在授权前调用相应的realm获取subject相应的角色权限,判断是否匹配.