008-shiro與spring web項目整合【二】認證、授權、session管理
一、認證
1、添加憑證匹配器
添加憑證匹配器實現md5加密校驗。
修改applicationContext-shiro.xml:
<!-- realm --> <bean id="customRealm" class="com.lhx.ssm.shiro.CustomRealm"> <!-- 將憑證匹配器設置到realm中,realm按照憑證匹配器的要求進行散列 --> <property name="credentialsMatcher" ref="credentialsMatcher"View Code/> </bean> <!-- 憑證匹配器 --> <bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <property name="hashAlgorithmName" value="md5"/> <property name="hashIterations" value="1"/> </bean>
2、修改realm認證方法
修改realm代碼從數據庫中查詢用戶身份信息,將sysService註入realm。
public class CustomRealm extends AuthorizingRealm { //註入service @Autowired private SysService sysService; // 設置realm的名稱 @Override public void setName(String name) { super.setName("customRealm"); }View Code// 支持什麽類型的token @Override public boolean supports(AuthenticationToken token) { return token instanceof UsernamePasswordToken; } // 用於認證 //realm的認證方法,從數據庫查詢用戶信息 @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { // token是用戶輸入的用戶名和密碼 // 第一步從token中取出用戶名 String userCode = (String) token.getPrincipal(); // 第二步:根據用戶輸入的userCode從數據庫查詢 SysUser sysUser = null; try { sysUser = sysService.findSysUserByUserCode(userCode); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // 如果查詢不到返回null if(sysUser==null){// return null; } // 從數據庫查詢到密碼 String password = sysUser.getPassword(); //鹽 String salt = sysUser.getSalt(); // 如果查詢到返回認證信息AuthenticationInfo //activeUser就是用戶身份信息 ActiveUser activeUser = new ActiveUser(); activeUser.setUserid(sysUser.getId()); activeUser.setUsercode(sysUser.getUsercode()); activeUser.setUsername(sysUser.getUsername()); //.. //根據用戶id取出菜單 List<SysPermission> menus = null; try { //通過service取出菜單 menus = sysService.findMenuListByUserId(sysUser.getId()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } //將用戶菜單 設置到activeUser activeUser.setMenus(menus); //將activeUser設置simpleAuthenticationInfo SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo( activeUser, password,ByteSource.Util.bytes(salt), this.getName()); return simpleAuthenticationInfo; } // ……授權下一個 }
二、授權
1.修改realm授權方法
修改realm代碼從數據庫中查詢權限信息,將sysService註入realm
public class CustomRealm extends AuthorizingRealm { //註入service @Autowired private SysService sysService; // 設置realm的名稱 @Override public void setName(String name) { super.setName("customRealm"); } // 支持什麽類型的token @Override public boolean supports(AuthenticationToken token) { return token instanceof UsernamePasswordToken; } // 用於認證 //realm的認證方法,從數據庫查詢用戶信息 @Override protected AuthenticationInfo doGetAuthenticationInfo( AuthenticationToken token) throws AuthenticationException { // token是用戶輸入的用戶名和密碼 // 第一步從token中取出用戶名 String userCode = (String) token.getPrincipal(); // 第二步:根據用戶輸入的userCode從數據庫查詢 SysUser sysUser = null; try { sysUser = sysService.findSysUserByUserCode(userCode); } catch (Exception e1) { // TODO Auto-generated catch block e1.printStackTrace(); } // 如果查詢不到返回null if(sysUser==null){// return null; } // 從數據庫查詢到密碼 String password = sysUser.getPassword(); //鹽 String salt = sysUser.getSalt(); // 如果查詢到返回認證信息AuthenticationInfo //activeUser就是用戶身份信息 ActiveUser activeUser = new ActiveUser(); activeUser.setUserid(sysUser.getId()); activeUser.setUsercode(sysUser.getUsercode()); activeUser.setUsername(sysUser.getUsername()); //.. //根據用戶id取出菜單 List<SysPermission> menus = null; try { //通過service取出菜單 menus = sysService.findMenuListByUserId(sysUser.getId()); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } //將用戶菜單 設置到activeUser activeUser.setMenus(menus); //將activeUser設置simpleAuthenticationInfo SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo( activeUser, password,ByteSource.Util.bytes(salt), this.getName()); return simpleAuthenticationInfo; } // 用於授權 @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()); } } /* List<String> permissions = new ArrayList<String>(); permissions.add("user:create");//用戶的創建 permissions.add("item:query");//商品查詢權限 permissions.add("item:add");//商品添加權限 permissions.add("item:edit");//商品修改權限 */ //.... //查到權限數據,返回授權信息(要包括 上邊的permissions) SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); //將上邊查詢到授權信息填充到simpleAuthorizationInfo對象中 simpleAuthorizationInfo.addStringPermissions(permissions); return simpleAuthorizationInfo; } }View Code
2、對controller開啟aop
在springmvc.xml中配置shiro註解支持,可在controller方法中使用shiro註解配置權限:
<!-- 開啟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>
3、權限註解控制
商品查詢controller方法添加權限(item:query):
// 查詢商品列表 @RequestMapping("/queryItem") @RequiresPermissions("item:query") public ModelAndView queryItem() throws Exception {
上邊代碼@RequiresPermissions("item:query")表示必須擁有“item:query”權限方可執行。
同理,商品修改controller方法添加權限(item:update):
@RequestMapping(value = "/editItem") @RequiresPermissions("item:update") public String editItem(@RequestParam(value = "id", required = true) Integer id, Model model) throws Exception
商品提交
// 商品修改提交 @RequestMapping("/editItemSubmit") @RequiresPermissions("item:update") public String editItemSubmit(@ModelAttribute("item") Items items,BindingResult result,MultipartFile pictureFile,Model model,HttpServletRequest request) throws Exception
4、jsp標簽控制
4.1、標簽簡介
a、Jsp頁面添加:
<%@ tagliburi="http://shiro.apache.org/tags" prefix="shiro" %>
b、詳細
標簽名稱 |
標簽條件(均是顯示標簽內容) |
<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"/> 顯示用戶身份中的屬性值
4.2、jsp頁面添加標簽
如果有商品修改權限頁面顯示“修改”鏈接。
<shiro:hasPermission name="item:update"> <a href="${pageContext.request.contextPath }/item/editItem.action?id=${item.id}">修改</a> </shiro:hasPermission>
三、session管理
和shiro整合後,使用shiro的session管理,shiro提供sessionDao操作 會話數據。
<!-- securityManager安全管理器 --> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="realm" ref="customRealm"/> <!-- 註入session管理器 --> <property name="sessionManager" ref="sessionManager"/> </bean> <!-- 會話管理器 --> <bean id="sessionManager" class="org.apache.shiro.web.session.mgt.DefaultWebSessionManager"> <!-- session的失效時長,單位毫秒 --> <property name="globalSessionTimeout" value="600000"/> <!-- 刪除失效的session --> <property name="deleteInvalidSessions" value="true"/> </bean>
008-shiro與spring web項目整合【二】認證、授權、session管理