如何在SpringMVC中使用Shiro實(shí)現(xiàn)權(quán)限控制

這篇文章將為大家詳細(xì)講解有關(guān)如何在Spring MVC中使用Shiro實(shí)現(xiàn)權(quán)限控制,文章內(nèi)容質(zhì)量較高,因此小編分享給大家做個(gè)參考,希望大家閱讀完這篇文章后對(duì)相關(guān)知識(shí)有一定的了解。

堅(jiān)守“ 做人真誠 · 做事靠譜 · 口碑至上 · 高效敬業(yè) ”的價(jià)值觀,專業(yè)網(wǎng)站建設(shè)服務(wù)10余年為成都工商代辦小微創(chuàng)業(yè)公司專業(yè)提供成都企業(yè)網(wǎng)站建設(shè)營銷網(wǎng)站建設(shè)商城網(wǎng)站建設(shè)手機(jī)網(wǎng)站建設(shè)小程序網(wǎng)站建設(shè)網(wǎng)站改版,從內(nèi)容策劃、視覺設(shè)計(jì)、底層架構(gòu)、網(wǎng)頁布局、功能開發(fā)迭代于一體的高端網(wǎng)站建設(shè)服務(wù)。

Apache Shiro 是一個(gè)功能強(qiáng)大且靈活的開放源代碼安全框架,可以細(xì)粒度地處理認(rèn)證 (Authentication),授權(quán) (Authorization),會(huì)話 (Session) 管理和加密 (cryptography) 等企業(yè)級(jí)應(yīng)用中常見的安全控制流程。 Apache Shiro 的首要目標(biāo)是易于使用和理解。 有時(shí)候安全性的流程控制會(huì)非常復(fù)雜,對(duì)開發(fā)人員來說是件很頭疼的事情,但并不一定如此。 框架就應(yīng)該盡可能地掩蓋復(fù)雜性,并公開一個(gè)簡潔而直觀的 API,從而簡化開發(fā)人員的工作,確保其應(yīng)用程序安全性。這次我們聊一聊如何在 Spring Web 應(yīng)用中使用 Shiro 實(shí)現(xiàn)權(quán)限控制。

Apache Shiro 是一個(gè)具有許多功能的綜合型應(yīng)用程序安全框架。 下圖為 Shiro 中的最主要的幾個(gè)功能:

如何在Spring MVC中使用Shiro實(shí)現(xiàn)權(quán)限控制

Shiro 的主要目標(biāo)是“應(yīng)用安全的四大基石” - 認(rèn)證,授權(quán),會(huì)話管理和加密:

  1. 身份驗(yàn)證:也就是通常所說的 “登錄”,為了證明用戶的行為所有者。

  2. 授權(quán):訪問控制的過程,即確定什么用戶可以訪問哪些內(nèi)容。

  3. 會(huì)話管理:即使在非 Web 應(yīng)用程序中,也可以管理用戶特定的會(huì)話,這也是 Shiro 的一大亮點(diǎn)。

  4. 加密技術(shù):使用加密算法保證數(shù)據(jù)的安全,非常易于使用。

架構(gòu)

從整體概念上理解,Shiro 的體系架構(gòu)有三個(gè)主要的概念:Subject (主體,也就是用戶),Security Manager (安全管理器)和 Realms (領(lǐng)域)。 下圖描述了這些組件之間的關(guān)系:

如何在Spring MVC中使用Shiro實(shí)現(xiàn)權(quán)限控制

這幾大組件可以這樣理解:

  1. Subject (主體):主體是當(dāng)前正在操作的用戶的特定數(shù)據(jù)集合。主體可以是一個(gè)人,也可以代表第三方服務(wù),守護(hù)進(jìn)程,定時(shí)任務(wù)或類似的東西,也就是幾乎所有與該應(yīng)用進(jìn)行交互的事物。

  2. Security Manager (安全管理器):它是 Shiro 的體系結(jié)構(gòu)的核心,扮演了類似于一把 “傘” 的角色,它主要負(fù)責(zé)協(xié)調(diào)內(nèi)部的各個(gè)組件,形成一張安全網(wǎng)。

  3. Realms (領(lǐng)域):Shiro 與應(yīng)用程序安全數(shù)據(jù)之間的 “橋梁”。當(dāng)需要實(shí)際與用戶帳戶等安全相關(guān)數(shù)據(jù)進(jìn)行交互以執(zhí)行認(rèn)證和授權(quán)時(shí),Shiro 將從 Realms 中獲取這些數(shù)據(jù)。

數(shù)據(jù)準(zhǔn)備

在 Web 應(yīng)用中,對(duì)安全的控制主要有角色、資源、權(quán)限(什么角色能訪問什么資源)幾個(gè)概念,一個(gè)用戶可以有多個(gè)角色,一個(gè)角色也可以訪問多個(gè)資源,也就是角色可以對(duì)應(yīng)多個(gè)權(quán)限。落實(shí)到數(shù)據(jù)庫設(shè)計(jì)上,我們至少需要建 5 張表:用戶表、角色表、資源表、角色-資源表、用戶-角色表,這 5 張表的結(jié)構(gòu)如下:

用戶表:


idusernamepassword
1張三123456
2李四666666
3王五000000

角色表:


idrolename
1管理員
2經(jīng)理
3員工

資源表:


idresname
1/user/add
2/user/delete
3/compony/info

角色-資源表:


idroleidresid
111
212
323

用戶-角色表:


iduseridroleid
111
212
313

對(duì)應(yīng)的 POJO 類如下:

/**
 * 用戶
 */
public class User {
 private Integer id;
 private String username;
 private String password;
 //getter & setter...
}
/**
 * 角色
 */
public class Role {
 private String id;
 private String rolename;
}
/**
 * 資源
 */
public class Resource {
 private String id;
 private String resname;
}
/**
 * 角色-資源
 */
public class RoleRes {
 private String id;
 private String roleid;
 private String resid;
}
/**
 * 用戶-角色
 */
public class UserRole {
 private String id;
 private String userid;
 private String roleid;
}

Spring 與 Shiro 整合的詳細(xì)步驟,請(qǐng)參閱我的博客 《 Spring 應(yīng)用中整合 Apache Shiro 》 。 這里補(bǔ)充一下:需要提前引入 Shiro 的依賴,打開mvnrepository.com,搜索 Shiro,我們需要前三個(gè)依賴,也就是 Shiro-Core、Shiro-Web 以及 Shiro-Spring,以 Maven 項(xiàng)目為例,在 pom.xml 中的 <dependencies> 節(jié)點(diǎn)下添加如下依賴:

<dependency>
 <groupId>org.apache.shiro</groupId>
 <artifactId>shiro-core</artifactId>
 <version>1.4.0</version>
</dependency>
<dependency>
 <groupId>org.apache.shiro</groupId>
 <artifactId>shiro-web</artifactId>
 <version>1.4.0</version>
</dependency>
<dependency>
 <groupId>org.apache.shiro</groupId>
 <artifactId>shiro-spring</artifactId>
 <version>1.4.0</version>
</dependency>

application-context.xml 中需要這樣配置 shiroFilter bean:

<!-- 配置shiro的過濾器工廠類,id- shiroFilter要和我們在web.xml中配置的過濾器一致 -->
<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
 <property name="securityManager" ref="securityManager"/>
 <!-- 登錄頁面 -->
 <property name="loginUrl" value="/login"/>
 <!-- 登錄成功后的頁面 -->
 <property name="successUrl" value="/index"/>
 <!-- 非法訪問跳轉(zhuǎn)的頁面 -->
 <property name="unauthorizedUrl" value="/403"/>
 <!-- 權(quán)限配置 -->
 <property name="filterChainDefinitions">
 <value>
  <!-- 無需認(rèn)證即可訪問的靜態(tài)資源,還可以添加其他 url -->
  /static/** = anon
  <!-- 除了上述忽略的資源,其他所有資源都需要認(rèn)證后才能訪問 -->
  /** = authc
 </value>
 </property>
</bean>

接下來就需要定義 Realm 了,自定義的 Realm 集成自 AuthorizingRealm 類:

public class MyRealm extends AuthorizingRealm {
 @Autowired
 private UserService userService;
 /**
 * 驗(yàn)證權(quán)限
 */
 @Override
 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
 String loginName = SecurityUtils.getSubject().getPrincipal().toString();
 if (loginName != null) {
 String userId = SecurityUtils.getSubject().getSession().getAttribute("userSessionId").toString();
 // 權(quán)限信息對(duì)象,用來存放查出的用戶的所有的角色及權(quán)限
 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
 // 用戶的角色集合
 ShiroUser shiroUser = (ShiroUser) principalCollection.getPrimaryPrincipal();
  info.setRoles(shiroUser.getRoles());
  info.addStringPermissions(shiroUser.getUrlSet());
 return info;
 }
 return null;
 }
 /**
 * 認(rèn)證回調(diào)函數(shù),登錄時(shí)調(diào)用
 */
 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) {
 String username = (String) token.getPrincipal();
 User user = new User();
 sysuser.setUsername(username);
 try {
 List<SysUser> users = userService.findByNames(user);
  List<String> roleList= userService.selectRoleNameListByUserId(users.get(0).getId());
 if (users.size() != 0) {
 String pwd = users.get(0).getPassword();
 // 當(dāng)驗(yàn)證都通過后,把用戶信息放在 session 里
 Session session = SecurityUtils.getSubject().getSession();
 session.setAttribute("userSession", users.get(0));
 session.setAttribute("userSessionId", users.get(0).getId());
 session.setAttribute("userRoles", org.apache.commons.lang.StringUtils.join(roleList,","));
  return new SimpleAuthenticationInfo(username,users.get(0).getPassword());
 } else {
  // 沒找到該用戶
 throw new UnknownAccountException();
 }
 } catch (Exception e) {
 System.out.println(e.getMessage());
 }
 return null;
 }
 /**
 * 更新用戶授權(quán)信息緩存.
 */
 public void clearCachedAuthorizationInfo(PrincipalCollection principals) {
 super.clearCachedAuthorizationInfo(principals);
 }
 /**
 * 更新用戶信息緩存.
 */
 public void clearCachedAuthenticationInfo(PrincipalCollection principals) {
 super.clearCachedAuthenticationInfo(principals);
 }
 /**
 * 清除用戶授權(quán)信息緩存.
 */
 public void clearAllCachedAuthorizationInfo() {
 getAuthorizationCache().clear();
 }
 /**
 * 清除用戶信息緩存.
 */
 public void clearAllCachedAuthenticationInfo() {
 getAuthenticationCache().clear();
 }
 /**
 * 清空所有緩存
 */
 public void clearCache(PrincipalCollection principals) {
 super.clearCache(principals);
 }
 /**
 * 清空所有認(rèn)證緩存
 */
 public void clearAllCache() {
 clearAllCachedAuthenticationInfo();
 clearAllCachedAuthorizationInfo();
 }
}

最后定義一個(gè)用戶登錄的控制器,接受用戶的登錄請(qǐng)求:

@Controller
public class UserController {
 /**
 * 用戶登錄
 */
 @PostMapping("/login")
 public String login(@Valid User user,BindingResult bindingResult,RedirectAttributes redirectAttributes){
 try {
  if(bindingResult.hasErrors()){
  return "login";
  }
  //使用權(quán)限工具進(jìn)行認(rèn)證,登錄成功后跳到 shiroFilter bean 中定義的 successUrl
  SecurityUtils.getSubject().login(new UsernamePasswordToken(user.getUsername(), user.getPassword()));
  return "redirect:index";
 } catch (AuthenticationException e) {
  redirectAttributes.addFlashAttribute("message","用戶名或密碼錯(cuò)誤");
  return "redirect:login";
 }
 }
 /**
 * 注銷登錄
 */
 @GetMapping("/logout")
 public String logout(RedirectAttributes redirectAttributes ){
 SecurityUtils.getSubject().logout();
 return "redirect:login";
 }
}

關(guān)于如何在Spring MVC中使用Shiro實(shí)現(xiàn)權(quán)限控制就分享到這里了,希望以上內(nèi)容可以對(duì)大家有一定的幫助,可以學(xué)到更多知識(shí)。如果覺得文章不錯(cuò),可以把它分享出去讓更多的人看到。

新聞標(biāo)題:如何在SpringMVC中使用Shiro實(shí)現(xiàn)權(quán)限控制
URL網(wǎng)址:http://muchs.cn/article46/piooeg.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)公司網(wǎng)站收錄、網(wǎng)站內(nèi)鏈、域名注冊、商城網(wǎng)站、外貿(mào)建站

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)

微信小程序開發(fā)