1、引入依賴 2、配置web.xml 3、配置applicationContext.xml,配置全局許可權 4、配置applicationContext.xml開啟cglib代理,啟動shiro許可權註解掃描 5、在action層中創建subject,交由Security Manager進行許可權校驗 6 ...
1、引入依賴
<!-- 許可權控制 框架 --> <dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-all</artifactId>
<version>1.2.2</version>
</dependency>
2、配置web.xml
<!-- spring框架提供,整合shiro框架
一定要在Struts攔截器之前配置
DelegatingFilterProxy在創建過程中,依賴一個對象,這個對象必須在applicationContext.xml 文件中間註冊,
而且註冊的時候聲明的ID必須和DelegatingFilterProxy聲明的filter-name保持一致
-->
<filter>
<filter-name>shiroFilterFactoryBean</filter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
<filter-name>shiroFilterFactoryBean</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
3、配置applicationContext.xml,配置全局許可權
1 <!-- 初始化shiro框架提供的過濾器 --> 2 <bean id="shiroFilterFactoryBean" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> 3 <!-- 註入安全管理器 --> 4 <property name="securityManager" ref="securityManager"/> 5 <!-- 許可權認證的頁面,登錄頁面 --> 6 <property name="loginUrl" value="/login.html"/> 7 <!-- 許可權認證成功以後要跳轉的頁面 --> 8 <property name="successUrl" value="/index.html"/> 9 <!-- 許可權認證失敗(許可權不足)以後要跳轉的頁面 只對攔截器生效,不對註解起效--> 10 <property name="unauthorizedUrl" value="/unauthorizedUrl.html"/> 11 <!--指定攔截規則--> 12 <property name="filterChainDefinitions" > 13 <!-- 14 authc:框架提供的過濾器,有許可權就放行,沒有許可權就攔截 15 anon:框架提供的過濾器,可以匿名訪問 16 perms:框架提供的過濾器,用戶請求資源的時候,會去檢查用戶是否擁有對應的許可權,如果有就放行,沒有,跳轉到unauthorizedUrl屬性指定的頁面 17 攔截的規則執行的時候是從上往下執行的,一旦有一個規則匹配成功.後面的規則就不再執行了 18 攔截規則不能折行 19 --> 20 <value> 21 /webService/** = anon 22 /upload/* = anon 23 /css/* = anon 24 /data/* = anon 25 /images/* = anon 26 /js/** = anon 27 /validatecode.jsp* = anon 28 /userAction_login.action = anon 29 /courierAction_pageQuery.action = perms["courierAction_pageQuery"] 30 /** = authc 31 </value> 32 </property> 33 34 </bean> 35 <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> 36 <!-- 配置realm類 --> 37 <property name="realm" ref="userRealm"/> 38 </bean>
4、配置applicationContext.xml開啟cglib代理,啟動shiro許可權註解掃描
1 <!-- 2 開啟事務註解 3 JDK代理 4 CGLib代理方式 5 proxy-target-class:true 使用cglib代理 6 proxy-target-class:false 使用jdk代理 7 --> 8 <tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager" /> 9 10 <!--基於spring的自動代理,創建service層的實現--> 11 <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"> 12 <!--開啟cglib 代理--> 13 <property name="proxyTargetClass" value="true"/> 14 </bean> 15 <!--配置切麵--> 16 <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> 17 <!--註入安全管理器 --> 18 <property name="securityManager" ref="securityManager"/> 19 </bean>
5、在action層中創建subject,交由Security Manager進行許可權校驗
1 @Action(value = "userAction_login",results = { 2 @Result(name = "success",location = "/index.html",type = "redirect"), 3 @Result(name = "error",location = "/login.html",type = "redirect") 4 }) 5 public String login(){ 6 String serverCode = (String) ServletActionContext.getRequest().getSession().getAttribute("key"); 7 8 if (StringUtils.isNotEmpty(checkCode) && StringUtils.isNotEmpty(serverCode)){ 9 Subject subject = SecurityUtils.getSubject(); 10 11 AuthenticationToken token = new UsernamePasswordToken( 12 getModel().getUsername(),getModel().getPassword()); 13 14 try { 15 subject.login(token); 16 //方法的返回值有Realm中doGetAuthenticationInfo方法定義SimpleAuthenticationInfo對象的時候,第一個參數決定的 17 User user = (User) subject.getPrincipal(); 18 ServletActionContext.getRequest().getSession().setAttribute("user",user); 19 return SUCCESS; 20 } catch (AuthenticationException e) { 21 e.printStackTrace(); 22 System.out.println("用戶名或密碼錯誤"); 23 } 24 } 25 return ERROR; 26 }
6、創建realm進行授權認證等
1 @Component 2 public class UserRealm extends AuthorizingRealm{ 3 4 @Autowired 5 private UserRepository userRepository; 6 7 @Autowired 8 private RoleRepository roleRepository; 9 10 @Autowired 11 private PermissionRepository permissionRepository; 12 13 //授權的方法 14 @Override 15 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { 16 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); 17 //根據當前用戶的用戶名去查詢對應的許可權和角色 18 Subject subject = SecurityUtils.getSubject(); 19 User user = (User) subject.getPrincipal(); 20 if ("admin".equals(user.getUsername())){ 21 List<Role> list = roleRepository.findAll(); 22 for (Role role : list) { 23 info.addRole(role.getKeyword()); 24 } 25 26 List<Permission> permissions = permissionRepository.findAll(); 27 for (Permission permission : permissions) { 28 info.addStringPermission(permission.getKeyword()); 29 } 30 }else { 31 List<Role> roles =roleRepository.findbyUid(user.getId()); 32 for (Role role : roles) { 33 info.addRole(role.getKeyword()); 34 } 35 List<Permission> permissions = permissionRepository.findbyUid(user.getId()); 36 for (Permission permission : permissions) { 37 info.addStringPermission(permission.getKeyword()); 38 } 39 } 40 41 return info; 42 } 43 //認證的方法 44 @Override 45 protected AuthenticationInfo doGetAuthenticationInfo( 46 AuthenticationToken authenticationToken) throws AuthenticationException { 47 48 UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) authenticationToken; 49 String username = usernamePasswordToken.getUsername(); 50 //根據用戶名查找用戶 51 User user = userRepository.findByUsername(username); 52 if (user != null){ 53 54 /*@param principal 當事人,主體,通常是從資料庫中查詢到的用戶 55 * @param credentials 憑證,密碼,是從資料庫中查詢出來的密碼 56 * @param realmName the realm from where the principal and credentials were acquired.*/ 57 //找到 -> 對比密碼 58 AuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),getName()); 59 // 比對成功-> 執行後續的邏輯 60 // 比對失敗-> 拋異常 61 return info; 62 } 63 //找不到 -> 拋異常 64 return null; 65 } 66 }
7、給對應的方法添加許可權註解(一般在service層)
1 @RequiresPermissions("batchDel") 2 //在調用方法時,框架就會檢查當前用戶是否有對應的許可權,如果有就放行,沒有就拋異常,啟用許可權註解必須開啟CGLib 3 @Override 4 public void batchDel(String ids) { 5 if(StringUtils.isNotEmpty(ids)){ 6 String[] strings = ids.split(","); 7 for (String string : strings) { 8 courierRepository.updateDelTagsById(Long.parseLong(string)); 9 } 10 } 11 }
8、給對應的jsp頁面添加許可權標簽進行顯示隱藏
<shiro:hasPermission name="courierAction_pageQuery"> { id : 'button-delete', text : '作廢', iconCls : 'icon-cancel', handler : doDelete } </shiro:hasPermission>
9、一般頁面的顯示的邏輯是:根據用戶所有擁有的角色和許可權進行動態生成菜單,從而只顯示用戶可操作的頁面。