前提就是在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 onclick="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";
}
