前提就是在Realm的授权方法中查询出权限并返回List<String>形式
@Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { // 从 principals获取主身份信息 // 将getPrimaryPrincipal方法返回值转为真实身份类型(在上边的doGetAuthenticationInfo认证通过填充到SimpleAuthenticationInfo中身份类型), ActiveUser activeUser = (ActiveUser) principals.getPrimaryPrincipal(); // 根据身份信息获取权限信息 // 从数据库获取到权限数据 List<SysPermission> permissionList = null; try { permissionList = sysService.findPermissionListByUserId(activeUser.getUserid()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } // 单独定一个集合对象 List<String> permissions = new ArrayList<String>(); if (permissionList != null) { for (SysPermission sysPermission : permissionList) { // 将数据库中的权限标签 符放入集合 permissions.add(sysPermission.getPercode()); } } // 查到权限数据,返回授权信息(要包括 上边的permissions) SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); // 将上边查询到授权信息填充到simpleAuthorizationInfo对象中 simpleAuthorizationInfo.addStringPermissions(permissions); return simpleAuthorizationInfo; }
1.applicationContext-shiro.xml配置
解释:访问上面这个需要有item:edit权限。
2.注解方法:
开启controller类aop支持
在springmvc.xml中配置:
<!-- 开启aop,对类代理 --> <aop:config proxy-target-class="true"></aop:config> <!-- 开启shiro注解支持 --> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager" /> </bean>
在controller方法中添加注解
3.JSP授权(页面上根据权限设置菜单显示与否)
Jsp页面添加:
<%@ tagliburi="http://shiro.apache.org/tags" prefix="shiro" %>
标签名称 | 标签条件(均是显示标签内容) |
<shiro:authenticated> | 登录之后 |
<shiro:notAuthenticated> | 不在登录状态时 |
<shiro:guest> | 用户在没有RememberMe时 |
<shiro:user> | 用户在RememberMe时 |
<shiro:hasAnyRoles name="abc,123" > | 在有abc或者123角色时 |
<shiro:hasRole name="abc"> | 拥有角色abc |
<shiro:lacksRole name="abc"> | 没有角色abc |
<shiro:hasPermission name="abc"> | 拥有权限资源abc |
<shiro:lacksPermission name="abc"> | 没有abc权限资源 |
<shiro:principal> | 显示用户身份名称 |
<shiro:principal property="username"/> 显示用户身份中的属性值
总结:
当调用controller的一个方法,由于该 方法加了@RequiresPermissions("item:query") ,shiro调用realm获取数据库中的权限信息,看"item:query"是否在权限数据中存在,如果不存在就拒绝访问,如果存在就授权通过。
当展示一个jsp页面时,页面中如果遇到<shiro:hasPermission name="item:update">,shiro调用realm获取数据库中的权限信息,看item:update是否在权限数据中存在,如果不存在就拒绝访问,如果存在就授权通过。
还有一种情况是有时候连接是在Ajax请求之后拼接到页面的,有时候也需要根据权限进行判断,项目中也遇到这种情况:
思路:在页面中定义一个JS全局变量,在shiro权限标签里面,如果有权限修改全局变量的值,在JS中根据全局变量的值判断是否有权限
(1)页面定义全局变量
<script>
var hasOperatingDepart=false;
<script>
(2)页面用shiro标签判断是否有权限:(有权限会执行JS脚本改变全局变量的值)
<shiro:hasPermission name="department:operating">
<script>
hasOperatingDepart = true;
</script>
</shiro:hasPermission>
(3)JS拼接的时候根据全局变量判断是否有权限:
// 有删除修改权限就显示连接
if (hasOperatingDepart) {
str += '<a οnclick="updateDepartment(this)" class="el_delButton">修改</a> ';
} else {
str += "-";
}
有时候我们需要在代码中判断用户是否有某些权限;
// 获取用户信息 Subject currentUser = SecurityUtils.getSubject(); boolean permitted = currentUser.isPermitted("exammanager:factory");// 判断是否有全厂管理的权限,有就不添加部门ID,没有就设为当前Session中的部门ID String departmentId = permitted ? null : departmentIdSession;
有时候我们需要在代码中判断用户是否有某些角色:
// 获取用户信息 Subject currentUser = SecurityUtils.getSubject(); boolean hasRole = currentUser.hasRole("教研室"); boolean hasRole2 = currentUser.hasRole("院长")
上面获取的主体的权限码是我们在授权的时候塞进去的,当然我们也可以将角色码也塞进去:
package cn.xm.jwxt.shiro; import cn.xm.jwxt.bean.system.Permission; import cn.xm.jwxt.bean.system.User; import cn.xm.jwxt.service.system.UserService; import cn.xm.jwxt.utils.ValidateCheck; import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authc.SimpleAuthenticationInfo; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.authz.SimpleAuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; import org.springframework.beans.factory.annotation.Autowired; import java.util.HashSet; import java.util.List; import java.util.Set; /** * @Author: qlq * @Description 自定义realm。根据上面传下来的token去数据库查信息,查到返回一个SimpleAuthenticationInfo,查不到返回null(用于shiro认证) * @Date: 21:56 2018/5/6 */ public class CustomRealm extends AuthorizingRealm { @Autowired private UserService userService; // 设置realm的名称 @Override public void setName(String name) { super.setName("customRealm"); } // realm的认证方法,从数据库查询用户信息 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String userCode=(String)token.getPrincipal();//获取token的主身份(登录的username User user = null; try { user = userService.getUserByUserCode(userCode); } catch (Exception e) { e.printStackTrace(); } AuthenticationInfo authenticationInfo=new SimpleAuthenticationInfo(user, user.getPassword(), this.getName()); return authenticationInfo; } // 用于授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //0.下面方法principals.getPrimaryPrincipal()获取的是在上面认证的时候装进AuthenticationInfo的对象 String userId=((User)(principals.getPrimaryPrincipal())).getUserid(); SimpleAuthorizationInfo simpleAuthorizationInfo=null; try { simpleAuthorizationInfo = new SimpleAuthorizationInfo(); //1.设置所有的权限(注意权限是以字符串的形式保存的权限码) List<Permission> permissions1 = userService.selectPermissionsByUserId(userId);//获取所有权限码 Set<String> permissions = new HashSet<>(); for(Permission permission:permissions1){ if(ValidateCheck.isNotNull(permission.getPermissioncode())){ permissions.add(permission.getPermissioncode()); } } if (permissions != null && permissions.size()>0) { simpleAuthorizationInfo.setStringPermissions(permissions); } //2.设置角色,角色也是以字符串的形式表示(这里存的是角色名字) Set<String> userRoleNames = userService.getUserRoleNameByUserId(userId); if(userRoleNames != null && userRoleNames.size()>0){ simpleAuthorizationInfo.setRoles(userRoleNames); } } catch (Exception e) { e.printStackTrace(); } return simpleAuthorizationInfo; } }
获取用户信息
@RequestMapping("/first.action") public String first(Model model)throws Exception{ //从shiro的session中取activeUser Subject subject = SecurityUtils.getSubject(); //取身份信息 ActiveUser activeUser = (ActiveUser) subject.getPrincipal(); //通过model传到页面 model.addAttribute("activeUser", activeUser); return "/first"; }