前提就是在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脚本改变全局变量的值)
|
1 2 3 4 5 |
|
(3)JS拼接的时候根据全局变量判断是否有权限:
|
1 2 3 4 5 6 |
|
有时候我们需要在代码中判断用户是否有某些权限;
// 获取用户信息
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";
}