赞
踩
目前越来越多的项目都用到了shiro框架,毕竟它简单、容易(呃呃~其实一点都不简单),花三分钟理解下面的三个概念,你就掌握了shiro百分之九十的核心。
一、Subject:主体,代表了当前 “用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是 Subject,如网络爬虫,机器人等;即一个抽象概念;所有 Subject 都绑定到 SecurityManager,与 Subject 的所有交互都会委托给 SecurityManager;可以把 Subject 认为是一个门面;SecurityManager 才是实际的执行者;
e.g.
Subject currentUser = SecurityUtils.getSubject();
try {
currentUser.login(new UsernamePasswordToken(username, password));
}
(username和password就是前端传过来的用户名和密码)
在你的controller代码中直接这样写,shiro就可以帮我们完成登录验证和授权了。
login方法的实现是这样的:
public void login(AuthenticationToken token) throws AuthenticationException {
this.clearRunAsIdentitiesInternal();
Subject subject = this.securityManager.login(this, token);
......
}
重点看这句话:
Subject subject = this.securityManager.login(this, token);
什么是SecurityManager?往下看
二、SecurityManager:安全管理器;即所有与安全有关的操作都会与 SecurityManager 交互;且它管理着所有 Subject;可以看出它是 Shiro 的核心,它负责与后边介绍的其他组件进行交互,如果学习过 SpringMVC,你可以把它看成 DispatcherServlet 前端控制器;
login方法最终会找到我们自己实现的Realm类:
(通过ModularRealmAuthenticator 类的doAuthenticate 方法)
protected AuthenticationInfo doAuthenticate(AuthenticationToken authenticationToken) throws AuthenticationException {
this.assertRealmsConfigured();
Collection<Realm> realms = this.getRealms();
return realms.size() == 1 ? this.doSingleRealmAuthentication((Realm)realms.iterator().next(), authenticationToken) : this.doMultiRealmAuthentication(realms, authenticationToken);
}
到这,SecurityManager就把Subject和Realm串联起来了。
实际上是通过Authenticator 完成身份认证,而SecurityManager继承自
Authenticator ,ModularRealmAuthenticator 是其默认实现之一,它委托多个Realm验证,通过验证规则通过 AuthenticationStrategy 接口指定。这个接口又有多个实现。ModularRealmAuthenticator 默认使用 AtLeastOneSuccessfulStrategy 策略。
三、Realm:域,Shiro 从从 Realm 获取安全数据(如用户、角色、权限),就是说 SecurityManager 要验证用户身份,那么它需要从 Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从 Realm 得到用户相应的角色 / 权限进行验证用户是否能进行操作;可以把 Realm 看成 DataSource,即安全数据源。
public class MyAuthorizingRealm extends AuthorizingRealm { @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { if (principals == null) { throw new AuthorizationException("PrincipalCollection method argument cannot be null."); } MyAccount = (MyAccount) getAvailablePrincipal(principals); Integer[] roleIds = admin.getRoleIds(); Set<String> roles = roleService.queryByIds(roleIds); Set<String> permissions = permissionService.queryByRoleIds(roleIds); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setRoles(roles); info.setStringPermissions(permissions); return info; } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { UsernamePasswordToken upToken = (UsernamePasswordToken) token; String username = upToken.getUsername(); String password = new String(upToken.getPassword()); if (StringUtils.isEmpty(username)) { throw new AccountException("用户名不能为空"); } if (StringUtils.isEmpty(password)) { throw new AccountException("密码不能为空"); } List<MyAccount> adminList = adminService.findAdmin(username); if (adminList.size() == 0) { throw new UnknownAccountException("找不到用户(" + username + ")的帐号信息"); } MyAccount = adminList.get(0); BCryptPasswordEncoder encoder = new BCryptPasswordEncoder(); if (!encoder.matches(password, admin.getPassword())) { throw new UnknownAccountException("找不到用户(" + username + ")的帐号信息"); } return new SimpleAuthenticationInfo(admin, password, getName()); } }
结束
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。