shiro權限控制


shiro權限控制

1.權限控制

1.1 什么是權限控制

白話文:控制某某用戶可以/不可以訪問某某功能。

我們今天的權限控制,實際上就是對資源加鎖,每個鎖都有一些規則,只有對應的鑰匙才能打開,我們根據用戶的角色,將鑰匙分配給不同用戶。

1.2 權限控制的方式

1、基於過濾器進行控制。比如我們servlet中的filter

2、基於注解進行控制。可以借助spring的AOP進行控制。

3、直接在業務代碼中判斷(不可取)

4、頁面標簽的權限控制——不太常用。

2.shiro簡介

2.1 功能

認證:即我們常說的登錄

授權:給予用戶資源權限

會話:當前認證用戶會話

緩存:緩存認證權限等

 

2.2 shiro核心流程

圖示

——這個圖只要是用shiro必定逃離不了。

2.3 權限控制方式:

filter方式

//設置過濾匹配路徑和判斷規則
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
filterChainDefinitionMap.put("/**", "anon");//可以匿名訪問
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);

其中,shiro的filter列表,盜了一張圖:

過濾器別名 對應的過濾器
anon org.apache.shiro.web.filter.authc.AnonymousFilter
authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter
authcBasic org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter
logout org.apache.shiro.web.filter.authc.LogoutFilter
noSessionCreation org.apache.shiro.web.filter.session.NoSessionCreationFilter
perms org.apache.shiro.web.filter.authz.PermissionsAuthorizationFilter
port org.apache.shiro.web.filter.authz.PortFilter
rest org.apache.shiro.web.filter.authz.HttpMethodPermissionFilter
roles org.apache.shiro.web.filter.authz.RolesAuthorizationFilter
ssl org.apache.shiro.web.filter.authz.SslFilter
user org.apache.shiro.web.filter.authc.UserFilter

注解方式

//在具體的方法上添加注解
@RequiresAuthentication :表示當前Subject已經認證:Subject.isAuthenticated()返回true
@RequiresUse:表示當前Subject已經身份驗證或者通過記住我登錄的
@RequiresGuest :表示當前Subject沒有身份驗證或通過記住我登錄過,即是游客身份
@RequiresRoles(value={“admin”, “user”}, logical= Logical.AND)
@RequiresPermissions(value={“user:select”, “user:all”}, logical= Logical.OR)

只是用注解是不生效的,需要添加配置

/**
* 注解支持:
*/
@Bean
@ConditionalOnMissingBean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
   DefaultAdvisorAutoProxyCreator defaultAAP = new DefaultAdvisorAutoProxyCreator();
   defaultAAP.setProxyTargetClass(true);
   return defaultAAP;
}

@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
   AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
   authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
   return authorizationAttributeSourceAdvisor;
}

 

標簽(了解)

注意,此處使用的是thymeleaf做視圖界面展示,並非jsp
<!--輸出當前用戶信息,通常為登錄帳號信息。如果存入的principal是對象,可以通過property取值-->
<span> <shiro:principal property="username"/> </span>

<!--驗證當前用戶是否擁有指定權限。 -->
<a shiro:hasPermission="user:select" href="#" >查看用戶列表</a><!-- 擁有權限 -->

<!--與hasPermission標簽邏輯相反,當前用戶沒有制定權限時,驗證通過。-->
<p shiro:lacksPermission="user:del"> 沒有權限 </p>

<!--驗證當前用戶是否擁有以下所有權限。-->
<p shiro:hasAllPermissions="user:view, user:add">擁有所有才能訪問</p>

<!--驗證當前用戶是否擁有以下任意一個權限。-->
<p shiro:hasAnyPermissions="user:view, user:del">擁有任意一個即可訪問</p>


<!--驗證當前用戶是否屬於該角色。-->
<a shiro:hasRole="role_admin" href="#">是role_admin角色</a>

<!--與hasRole標簽邏輯相反,當用戶不屬於該角色時驗證通過。-->
<p shiro:lacksRole="role_admin">我沒有role_admin角色</p>

<!--驗證當前用戶是否屬於以下所有角色。-->
<p shiro:hasAllRoles="developer, admin"> 角色與判斷 </p>

<!--驗證當前用戶是否屬於以下任意一個角色。-->
<p shiro:hasAnyRoles="admin, vip, developer"> 角色或判斷 </p>

<!--驗證當前用戶是否為“訪客”,即未認證(包含未記住)的用戶。-->
<p shiro:guest="">訪客 未認證</a></p>
   
<!--已認證通過的用戶。不包含已記住的用戶,這是與user標簽的區別所在。-->
<p shiro:authenticated=""> <span shiro:principal=""></span> </p>  

<!--未認證通過用戶,與authenticated標簽相對應。-->
<!--與guest標簽的區別是,該標簽包含已記住用戶。-->
<p shiro:notAuthenticated=""> 未認證通過用戶 </p>

 

3.springboot整合shiro

3.1 SecurityManager

@Bean
public SecurityManager securityManager(){
   DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
   List<Realm> realms = new ArrayList<Realm>();
   realms.add(customRealm());
   securityManager.setRealms(realms);
   securityManager.setSessionManager(sessionManager());
   return securityManager;
}

 

3.2 Realm

//主要用作封裝認證、授權信息,返回給安全管理器處理
@Bean
public CustomRealm customRealm(){
   CustomRealm customRealm = new CustomRealm();
   //設置密碼校驗算法——需要和加密算法一致
   customRealm.setCredentialsMatcher(credentialsMatcher());
   return customRealm;
}

@Bean
public CredentialsMatcher credentialsMatcher(){
   HashedCredentialsMatcher hashedCredentialsMatcher = new HashedCredentialsMatcher();
   hashedCredentialsMatcher.setHashAlgorithmName("md5");//散列算法:這里使用MD5算法;
   //       hashedCredentialsMatcher.setHashIterations(2);
   return hashedCredentialsMatcher;
}

 

3.3 ShiroFilter

@Bean
public ShiroFilterFactoryBean shiroFilter2(SecurityManager securityManager){
   ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
   shiroFilterFactoryBean.setSecurityManager(securityManager);
   shiroFilterFactoryBean.setLoginUrl("/admin/toPage");
   Map<String, String> filterChainDefinitionMap = new LinkedHashMap<String, String>();
   //訪問控制
   filterChainDefinitionMap.put("/admin/toPage", "anon");//可以匿名訪問
   filterChainDefinitionMap.put("/admin/login", "anon");//可以匿名訪問
   filterChainDefinitionMap.put("/storage/list", "perms[user:select]");//可以匿名訪問
   //       filterChainDefinitionMap.put("/", "anon");//可以匿名訪問
   filterChainDefinitionMap.put("/**", "anon");//可以匿名訪問
   shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
   return shiroFilterFactoryBean;
}

3.4 SessionManager

@Bean
public SessionManager sessionManager() {
   DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
   sessionManager.setSessionDAO(redisSessionDAO());

   //設置會話過期時間
   sessionManager.setGlobalSessionTimeout(3*60*1000); //默認半小時
   sessionManager.setDeleteInvalidSessions(true); //默認自定調用SessionDAO的delete方法刪除會話

   //設置會話定時檢查
   sessionManager.setSessionValidationInterval(180000); //默認一小時
   sessionManager.setSessionValidationSchedulerEnabled(true);
   return sessionManager;
}

@Bean
public SessionDAO redisSessionDAO(){
   ShiroSessionRedisDAO redisDAO = new ShiroSessionRedisDAO();
   return redisDAO;
}

 

 

3.4 用戶新增

在controller中接收新增用戶后,交給service的saveAdmin做密碼加密后保存

public void saveAdmin(Administrator admin) {
   //對密碼進行加密處理
   //1.得到明文密碼
   String password = admin.getPassword();
   //2.生成隨機鹽 4-8位的隨機數字
   String randomSalt = RandomStringUtils.randomNumeric(4, 8);
   admin.setPrivateSalt(randomSalt);
   //3.md5加密 添加隨機鹽,加密次數1次(當然,這個一次可以配置在配置文件在,此處注入讀取)
   Md5Hash md5Hash = new Md5Hash(password,randomSalt,1);
   String hashPwd = md5Hash.toString();
   admin.setPassword(hashPwd);
   userMapper.insert(admin);
}

 

3.5 用戶登錄

認證

@Controller
@RequestMapping("/admin")
public class LoginController {

   @PostMapping("/login")
   public String login(
       @RequestParam("username") String username,
       @RequestParam("password") String password,Model map){
       try {
           Subject subject = SecurityUtils.getSubject();
           //處理登錄的用戶名密碼token
           UsernamePasswordToken token =
               new UsernamePasswordToken(username, password);
           //登錄(開始認證)
           subject.login(token);
           return "redirect:/admin/main";
      }catch (UnknownAccountException ukactException){
           //用戶不存在異常
           ukactException.printStackTrace();
           map.addAttribute("err_msg","用戶不存在");
           return "login";
      }catch (IncorrectCredentialsException credentialExctption){
           credentialExctption.printStackTrace();
           map.addAttribute("err_msg","密碼錯誤");
           return "login";
      }catch (Exception e){
           e.printStackTrace();
           map.addAttribute("err_msg","服務器錯誤,請重試");
           return "login";
      }
  }
}

 

3.6 用戶訪問(權限控制)

 

4.其他

4.1 thymeleaf中使用shiro標簽的支持

依賴坐標:

<dependency>
   <groupId>com.github.theborakompanioni</groupId>
   <artifactId>thymeleaf-extras-shiro</artifactId>
   <version>2.0.0</version>
</dependency>

配置支持:

@Bean
public ShiroDialect shiroDialect(){
   return new ShiroDialect();
}

 

4.2 request判斷ajax請求

//通過頭X-Requested-With=XMLHttpRequest來判斷
request.getHeader("X-Requested-With");

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM