一,shiro中的概念
(注:本博客所有图片皆来自于网络)
1,Authentication:用户认证/登录
2,Authorization:对用户的角色和权限进行验证。即判断用户是否有某个角色或者某样权限(角色,权限数据可以存储在数据库中或者文件中)。
3,SessionManagement:session管理与web中servlet的session的数据是共通的。
4,Cryptography:用户加密。(我一般没有使用这个功能,平时使用SimpleHash 进行md5 加密密码)。
5,Caching:缓存,将用的的角色和权限进行缓存。
…
二,了解shiro
1,Subject:通过SecurityUtils.getSubject()进行获取Subject对象。它表示一个“对象”,它可以是登录的用户,也可以是其它与shiro联系 的“对象”。
2,SecurityManager:安全管理者管理着subject,subject的所有操作都要通过SecurityManager.
3,Realm :”域“,realm从数据库或者其它地方获取用户/角色/权限数据,可以看成一个安全数据源。SecurityManager进行用户身份验证时,会从Realm拿数据进行比较。
注: 无论是用户的身份验证还是角色和权限的管理,推荐使用AuthorizingRealm.。
三,用户身份验证
无论是用户的身份验证还是角色和权限的管理,推荐使用AuthorizingRealm.。
UsernamePasswordToken token = new UsernamePasswordToken(user.getName(), user.getPassword());
try {
//将用户的数据token 最终传递到Realm中进行对比
subject.login(token);
} catch (AuthenticationException e) {
//验证错误
return false;
}
return subject.isAuthenticated();
从上图可以看到,当Subject.logout(token)时,就会与SecurityManager交互,SecurityManager就会使用Realm获取数据进行身份验证。这是使用AuthorizingRealm。
1,继承AuthorizingRealm,重写它的doGetAuthencationInfo(AuthenticationToken token)方法,代码如下:
//验证方法。
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
//获取传递进来的账号密码
UsernamePasswordToken t = (UsernamePasswordToken) token;
String userName= token.getPrincipal().toString();
String password =new String(t.getPassword());
//获取数据库中的密码
User user = new DAO().getUser(userName);
String passwordInDB = user.getPassword();
//获取数据库中的盐
String salt = user.getSalt();
String passwordEncoded = new SimpleHash("md5",password,salt,2).toString();
//判断是否相等()
if(null==user || !passwordEncoded.equals(passwordInDB))
throw new AuthenticationException();
//认证信息里存放账号密码, getName() 是当前Realm的继承方法,通常返回当前类名 :databaseRealm
SimpleAuthenticationInfo a = new SimpleAuthenticationInfo(userName,password,getName());
return a;
}
四,角色/权限管理
private static boolean hasRole(User user, String role) {
Subject subject = getSubject(user);
return subject.hasRole(role);
}
private static boolean isPermitted(User user, String permit) {
Subject subject = getSubject(user);
return subject.isPermitted(permit);
}
通过前面图片i集上面的代码可以看到,调用subject.hasRole(role) /isPermitted(permit) 判断用户是否有当前角色/权限 ,这时SecurityManager会从Realm拿数据然后进行比较。这是Realm代表AuthorizingRealm。代码如下:
//授权 方法
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//能进入到这里,表示账号已经通过验证了
String userName =(String) principalCollection.getPrimaryPrincipal();
//通过DAO获取角色和权限
Set<String> permissions = new DAO().listPermissions(userName);
Set<String> roles = new DAO().listRoles(userName);
//授权对象
SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo();
//把通过DAO获取到的角色和权限放进去
simpleAuthorizationInfo.setStringPermissions(permissions);
simpleAuthorizationInfo.setRoles(roles);
return simpleAuthorizationInfo;
}
通过重写AuthorizingRealm的doGetAuthorizationInifo(PrincipalCollection principal)进行获取当前用户的角色/权限,进行设置当前用户的角色与权限。
———————————————————————————————————————————————
如果有什么错误,欢迎各位客官指出。