<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Spring Boot 中集成 Shiro

          共 18589字,需瀏覽 38分鐘

           ·

          2021-05-15 06:27

          ????關(guān)注后回復(fù) “進(jìn)群” ,拉你進(jìn)程序員交流群????

          作者丨武哥

          來(lái)源丨武哥聊編程

          Shiro 是一個(gè)強(qiáng)大、簡(jiǎn)單易用的 Java 安全框架,主要用來(lái)更便捷的認(rèn)證,授權(quán),加密,會(huì)話管等等,可為任何應(yīng)用提供安全保障。本課程主要來(lái)介紹 Shiro 的認(rèn)證和授權(quán)功能。

          1. Shiro 三大核心組件

          Shiro 有三大核心的組件:SubjectSecurityManagerRealm。先來(lái)看一下它們之間的關(guān)系。

          三大核心組件的關(guān)系
          1. Subject:認(rèn)證主體。它包含兩個(gè)信息:Principals 和 Credentials。看一下這兩個(gè)信息具體是什么。

          Principals:身份。可以是用戶(hù)名,郵件,手機(jī)號(hào)碼等等,用來(lái)標(biāo)識(shí)一個(gè)登錄主體身份;
          Credentials:憑證。常見(jiàn)有密碼,數(shù)字證書(shū)等等。

          說(shuō)白了,就是需要認(rèn)證的東西,最常見(jiàn)的就是用戶(hù)名密碼了,比如用戶(hù)在登錄的時(shí)候,Shiro 需要去進(jìn)行身份認(rèn)證,就需要 Subject 認(rèn)證主體。

          1. SecurityManager:安全管理員。這是 Shiro 架構(gòu)的核心,它就像 Shiro 內(nèi)部所有原件的保護(hù)傘一樣。我們?cè)陧?xiàng)目中一般都會(huì)配置 SecurityManager,開(kāi)發(fā)人員大部分精力主要是在 Subject 認(rèn)證主體上面。我們?cè)谂c Subject 進(jìn)行交互的時(shí)候,實(shí)際上是 SecurityManager 在背后做一些安全操作。
          2. Realm:Realm 是一個(gè)域,它是連接 Shiro 和具體應(yīng)用的橋梁,當(dāng)需要與安全數(shù)據(jù)交互的時(shí)候,比如用戶(hù)賬戶(hù)、訪問(wèn)控制等,Shiro 就會(huì)從一個(gè)或多個(gè) Realm 中去查找。我們可以把 Realm 看成 DataSource,即安全數(shù)據(jù)源,一般我們會(huì)自己定制 Realm,在自定義 Realm 中,我們一般會(huì)從數(shù)據(jù)庫(kù)中獲取和認(rèn)證相關(guān)的信息,這在下文自定義 Realm 部分會(huì)詳細(xì)說(shuō)明。

          1. Shiro 身份和權(quán)限認(rèn)證

          1.2 Shiro 身份認(rèn)證

          我們來(lái)分析一下 Shiro 身份認(rèn)證的過(guò)程,看一下官方的一個(gè)認(rèn)證圖:

          認(rèn)證過(guò)程

          Step1:應(yīng)用程序代碼在調(diào)用 Subject.login(token) 方法后,傳入代表最終用戶(hù)的身份和憑證的 AuthenticationToken 實(shí)例 token。

          Step2:將 Subject 實(shí)例委托給應(yīng)用程序的 SecurityManager(Shiro的安全管理)來(lái)開(kāi)始實(shí)際的認(rèn)證工作。這里開(kāi)始真正的認(rèn)證工作了。

          Step3,4,5:然后 SecurityManager 就會(huì)根據(jù)具體的 realm 去進(jìn)行安全認(rèn)證了。從圖中可以看出,realm 可以自定義(Custom Realm)。

          1.3 Shiro 權(quán)限認(rèn)證

          權(quán)限認(rèn)證,也就是訪問(wèn)控制,即在應(yīng)用中控制誰(shuí)能訪問(wèn)哪些資源。在權(quán)限認(rèn)證中,最核心的三個(gè)要素是:權(quán)限,角色和用戶(hù)。

          權(quán)限(permission):即操作資源的權(quán)利,比如訪問(wèn)某個(gè)頁(yè)面,以及對(duì)某個(gè)模塊的數(shù)據(jù)的添加,修改,刪除,查看的權(quán)利;角色(role):指的是用戶(hù)擔(dān)任的的角色,一個(gè)角色可以有多個(gè)權(quán)限;用戶(hù)(user):在 Shiro 中,代表訪問(wèn)系統(tǒng)的用戶(hù),即上面提到的 Subject 認(rèn)證主體。

          它們之間的的關(guān)系可以用下圖來(lái)表示:

          用戶(hù)、角色和權(quán)限的關(guān)系

          一個(gè)用戶(hù)可以有多個(gè)角色,而不同的角色可以有不同的權(quán)限,也可由有相同的權(quán)限。比如說(shuō)現(xiàn)在有三個(gè)角色,1是普通角色,2也是普通角色,3是管理員,角色1只能查看信息,角色2只能添加信息,管理員都可以,而且還可以刪除信息,類(lèi)似于這樣。

          2. Spring Boot 集成 Shiro 過(guò)程

          2.1 依賴(lài)導(dǎo)入

          Spring Boot 2.0.3 集成 Shiro 需要導(dǎo)入如下 starter 依賴(lài):

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

          2.2 數(shù)據(jù)庫(kù)表數(shù)據(jù)初始化

          這里主要涉及到三張表:用戶(hù)表、角色表和權(quán)限表,其實(shí)在 demo 中,我們完全可以自己模擬一下,不用建表,但是為了更加接近實(shí)際情況,我們還是加入 mybatis,來(lái)操作數(shù)據(jù)庫(kù)。下面是數(shù)據(jù)庫(kù)表的腳本。

          CREATE TABLE `t_role` (
            `id` int(11NOT NULL AUTO_INCREMENT COMMENT '主鍵',
            `rolename` varchar(20DEFAULT NULL COMMENT '角色名稱(chēng)',
            PRIMARY KEY (`id`)
          ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

          CREATE TABLE `t_user` (
            `id` int(11NOT NULL AUTO_INCREMENT COMMENT '用戶(hù)主鍵',
            `username` varchar(20NOT NULL COMMENT '用戶(hù)名',
            `password` varchar(20NOT NULL COMMENT '密碼',
            `role_id` int(11DEFAULT NULL COMMENT '外鍵關(guān)聯(lián)role表',
            PRIMARY KEY (`id`),
            KEY `role_id` (`role_id`),
            CONSTRAINT `t_user_ibfk_1` FOREIGN KEY (`role_id`REFERENCES `t_role` (`id`)
          ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8

          CREATE TABLE `t_permission` (
            `id` int(11NOT NULL AUTO_INCREMENT COMMENT '主鍵',
            `permissionname` varchar(50NOT NULL COMMENT '權(quán)限名',
            `role_id` int(11DEFAULT NULL COMMENT '外鍵關(guān)聯(lián)role',
            PRIMARY KEY (`id`),
            KEY `role_id` (`role_id`),
            CONSTRAINT `t_permission_ibfk_1` FOREIGN KEY (`role_id`REFERENCES `t_role` (`id`)
          ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8

          其中,t_user,t_role 和 t_permission,分別存儲(chǔ)用戶(hù)信息,角色信息和權(quán)限信息,表建立好了之后,我們往表里插入一些測(cè)試數(shù)據(jù)。t_user 表:

          idusernamepasswordrole_id
          1csdn11234561
          2csdn21234562
          3csdn31234563

          t_role 表:

          idrolename
          1admin
          2teacher
          3student

          t_permission 表:

          idpermissionnamerole_id
          1user:*1
          2student:*2

          解釋一下這里的權(quán)限:user:*表示權(quán)限可以是 user:create 或者其他,* 處表示一個(gè)占位符,我們可以自己定義,具體的會(huì)在下文 Shiro 配置那里說(shuō)明。

          2.2 自定義 Realm

          有了數(shù)據(jù)庫(kù)表和數(shù)據(jù)之后,我們開(kāi)始自定義 realm,自定義 realm 需要繼承 AuthorizingRealm 類(lèi),因?yàn)樵擃?lèi)封裝了很多方法,它也是一步步繼承自 Realm 類(lèi)的,繼承了 AuthorizingRealm 類(lèi)后,需要重寫(xiě)兩個(gè)方法:

          doGetAuthenticationInfo() 方法:用來(lái)驗(yàn)證當(dāng)前登錄的用戶(hù),獲取認(rèn)證信息
          doGetAuthorizationInfo() 方法:用來(lái)為當(dāng)前登陸成功的用戶(hù)授予權(quán)限和角色

          具體實(shí)現(xiàn)如下,相關(guān)的解釋我放在代碼的注釋中,這樣更加方便直觀:

          /**
           * 自定義realm
           * @author shengwu ni
           */

          public class MyRealm extends AuthorizingRealm {

              @Resource
              private UserService userService;

              @Override
              protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
                  // 獲取用戶(hù)名
                  String username = (String) principalCollection.getPrimaryPrincipal();
                  SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
                  // 給該用戶(hù)設(shè)置角色,角色信息存在t_role表中取
                  authorizationInfo.setRoles(userService.getRoles(username));
                  // 給該用戶(hù)設(shè)置權(quán)限,權(quán)限信息存在t_permission表中取
                  authorizationInfo.setStringPermissions(userService.getPermissions(username));
                  return authorizationInfo;
              }

              @Override
              protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
                  // 根據(jù)token獲取用戶(hù)名,如果您不知道該該token怎么來(lái)的,先可以不管,下文會(huì)解釋
                  String username = (String) authenticationToken.getPrincipal();
                  // 根據(jù)用戶(hù)名從數(shù)據(jù)庫(kù)中查詢(xún)?cè)撚脩?hù)
                  User user = userService.getByUsername(username);
                  if(user != null) {
                      // 把當(dāng)前用戶(hù)存到session中
                      SecurityUtils.getSubject().getSession().setAttribute("user", user);
                      // 傳入用戶(hù)名和密碼進(jìn)行身份認(rèn)證,并返回認(rèn)證信息
                      AuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user.getUsername(), user.getPassword(), "myRealm");
                      return authcInfo;
                  } else {
                      return null;
                  }
              }
          }

          從上面兩個(gè)方法中可以看出:驗(yàn)證身份的時(shí)候是根據(jù)用戶(hù)輸入的用戶(hù)名先從數(shù)據(jù)庫(kù)中查出該用戶(hù)名對(duì)應(yīng)的用戶(hù),這時(shí)候并沒(méi)有涉及到密碼,也就是說(shuō)到這一步的時(shí)候,即使用戶(hù)輸入的密碼不對(duì),也是可以查出來(lái)該用戶(hù)的,然后將該用戶(hù)的正確信息封裝到 authcInfo 中返回給 Shiro,接下來(lái)就是Shiro的事了,它會(huì)根據(jù)這里面的真實(shí)信息與用戶(hù)前臺(tái)輸入的用戶(hù)名和密碼進(jìn)行校驗(yàn), 這個(gè)時(shí)候也要校驗(yàn)密碼了,如果校驗(yàn)通過(guò)就讓用戶(hù)登錄,否則跳轉(zhuǎn)到指定頁(yè)面。同理,權(quán)限驗(yàn)證的時(shí)候也是先根據(jù)用戶(hù)名從數(shù)據(jù)庫(kù)中獲取與該用戶(hù)名有關(guān)的角色和權(quán)限,然后封裝到 authorizationInfo 中返回給 Shiro。

          2.3 Shiro 配置

          自定義的 realm 寫(xiě)好了,接下來(lái)需要對(duì) Shiro 進(jìn)行配置了。我們主要配置三個(gè)東西:自定義 realm、安全管理器 SecurityManager 和 Shiro 過(guò)濾器。如下:

          配置自定義 realm:

          @Configuration
          public class ShiroConfig {

              private static final Logger logger = LoggerFactory.getLogger(ShiroConfig.class);

              /**
               * 注入自定義的realm
               * @return MyRealm
               */

              @Bean
              public MyRealm myAuthRealm() {
                  MyRealm myRealm = new MyRealm();
                  logger.info("====myRealm注冊(cè)完成=====");
                  return myRealm;
              }
          }

          配置安全管理器 SecurityManager:

          @Configuration
          public class ShiroConfig {

              private static final Logger logger = LoggerFactory.getLogger(ShiroConfig.class);

              /**
               * 注入安全管理器
               * @return SecurityManager
               */

              @Bean
              public SecurityManager securityManager() {
                  // 將自定義realm加進(jìn)來(lái)
                  DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(myAuthRealm());
                  logger.info("====securityManager注冊(cè)完成====");
                  return securityManager;
              }
          }

          配置 SecurityManager 時(shí),需要將上面的自定義 realm 添加進(jìn)來(lái),這樣的話 Shiro 才會(huì)走到自定義的 realm 中。

          配置 Shiro 過(guò)濾器:

          @Configuration
          public class ShiroConfig {

              private static final Logger logger = LoggerFactory.getLogger(ShiroConfig.class);
              
              /**
               * 注入Shiro過(guò)濾器
               * @param securityManager 安全管理器
               * @return ShiroFilterFactoryBean
               */

              @Bean
              public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
                  // 定義shiroFactoryBean
                  ShiroFilterFactoryBean shiroFilterFactoryBean=new ShiroFilterFactoryBean();

                  // 設(shè)置自定義的securityManager
                  shiroFilterFactoryBean.setSecurityManager(securityManager);

                  // 設(shè)置默認(rèn)登錄的url,身份認(rèn)證失敗會(huì)訪問(wèn)該url
                  shiroFilterFactoryBean.setLoginUrl("/login");
                  // 設(shè)置成功之后要跳轉(zhuǎn)的鏈接
                  shiroFilterFactoryBean.setSuccessUrl("/success");
                  // 設(shè)置未授權(quán)界面,權(quán)限認(rèn)證失敗會(huì)訪問(wèn)該url
                  shiroFilterFactoryBean.setUnauthorizedUrl("/unauthorized");

                  // LinkedHashMap是有序的,進(jìn)行順序攔截器配置
                  Map<String,String> filterChainMap = new LinkedHashMap<>();

                  // 配置可以匿名訪問(wèn)的地址,可以根據(jù)實(shí)際情況自己添加,放行一些靜態(tài)資源等,anon表示放行
                  filterChainMap.put("/css/**""anon");
                  filterChainMap.put("/imgs/**""anon");
                  filterChainMap.put("/js/**""anon");
                  filterChainMap.put("/swagger-*/**""anon");
                  filterChainMap.put("/swagger-ui.html/**""anon");
                  // 登錄url 放行
                  filterChainMap.put("/login""anon");

                  // “/user/admin” 開(kāi)頭的需要身份認(rèn)證,authc表示要身份認(rèn)證
                  filterChainMap.put("/user/admin*""authc");
                  // “/user/student” 開(kāi)頭的需要角色認(rèn)證,是“admin”才允許
                  filterChainMap.put("/user/student*/**""roles[admin]");
                  // “/user/teacher” 開(kāi)頭的需要權(quán)限認(rèn)證,是“user:create”才允許
                  filterChainMap.put("/user/teacher*/**""perms[\"user:create\"]");

                  // 配置logout過(guò)濾器
                  filterChainMap.put("/logout""logout");

                  // 設(shè)置shiroFilterFactoryBean的FilterChainDefinitionMap
                  shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainMap);
                  logger.info("====shiroFilterFactoryBean注冊(cè)完成====");
                  return shiroFilterFactoryBean;
              }
          }

          配置 Shiro 過(guò)濾器時(shí)會(huì)傳入一個(gè)安全管理器,可以看出,這是一環(huán)套一環(huán),reaml -> SecurityManager -> filter。在過(guò)濾器中,我們需要定義一個(gè) shiroFactoryBean,然后將 SecurityManager 添加進(jìn)來(lái),結(jié)合上面代碼可以看出,要配置的東西主要有:

          默認(rèn)登錄的 url:身份認(rèn)證失敗會(huì)訪問(wèn)該 url 認(rèn)證成功之后要跳轉(zhuǎn)的 url 權(quán)限認(rèn)證失敗會(huì)訪問(wèn)該 url 需要攔截或者放行的 url:這些都放在一個(gè) map 中

          從上述代碼中可以看出,在 map 中,針對(duì)不同的 url,有不同的權(quán)限要求,這里總結(jié)一下常用的幾個(gè)權(quán)限。

          Filter說(shuō)明
          anon開(kāi)放權(quán)限,可以理解為匿名用戶(hù)或游客,可以直接訪問(wèn)的
          authc需要身份認(rèn)證的
          logout注銷(xiāo),執(zhí)行后會(huì)直接跳轉(zhuǎn)到 shiroFilterFactoryBean.setLoginUrl(); 設(shè)置的 url,即登錄頁(yè)面
          roles[admin]參數(shù)可寫(xiě)多個(gè),表示是某個(gè)或某些角色才能通過(guò),多個(gè)參數(shù)時(shí)寫(xiě) roles["admin,user"],當(dāng)有多個(gè)參數(shù)時(shí)必須每個(gè)參數(shù)都通過(guò)才算通過(guò)
          perms[user]參數(shù)可寫(xiě)多個(gè),表示需要某個(gè)或某些權(quán)限才能通過(guò),多個(gè)參數(shù)時(shí)寫(xiě) perms[“user, admin”],當(dāng)有多個(gè)參數(shù)時(shí)必須每個(gè)參數(shù)都通過(guò)才算通過(guò)

          2.4 使用 Shiro 進(jìn)行認(rèn)證

          到這里,我們對(duì) Shiro 的準(zhǔn)備工作都做完了,接下來(lái)開(kāi)始使用 Shiro 進(jìn)行認(rèn)證工作。我們首先來(lái)設(shè)計(jì)幾個(gè)接口:

          接口一:使用 http://localhost:8080/user/admin 來(lái)驗(yàn)證身份認(rèn)證 接口二:使用 http://localhost:8080/user/student 來(lái)驗(yàn)證角色認(rèn)證 接口三:使用 http://localhost:8080/user/teacher 來(lái)驗(yàn)證權(quán)限認(rèn)證 接口四:使用 http://localhost:8080/user/login 來(lái)實(shí)現(xiàn)用戶(hù)登錄

          然后來(lái)一下認(rèn)證的流程:

          流程一:直接訪問(wèn)接口一(此時(shí)還未登錄),認(rèn)證失敗,跳轉(zhuǎn)到 login.html 頁(yè)面讓用戶(hù)登錄,登錄會(huì)請(qǐng)求接口四,實(shí)現(xiàn)用戶(hù)登錄功能,此時(shí) Shiro 已經(jīng)保存了用戶(hù)信息了。流程二:再次訪問(wèn)接口一(此時(shí)用戶(hù)已經(jīng)登錄),認(rèn)證成功,跳轉(zhuǎn)到 success.html 頁(yè)面,展示用戶(hù)信息。流程三:訪問(wèn)接口二,測(cè)試角色認(rèn)證是否成功。流程四:訪問(wèn)接口三,測(cè)試權(quán)限認(rèn)證是否成功。

          2.4.1 身份、角色、權(quán)限認(rèn)證接口

          @Controller
          @RequestMapping("/user")
          public class UserController {

              /**
               * 身份認(rèn)證測(cè)試接口
               * @param request
               * @return
               */

              @RequestMapping("/admin")
              public String admin(HttpServletRequest request) {
                  Object user = request.getSession().getAttribute("user");
                  return "success";
              }

              /**
               * 角色認(rèn)證測(cè)試接口
               * @param request
               * @return
               */

              @RequestMapping("/student")
              public String student(HttpServletRequest request) {
                  return "success";
              }

              /**
               * 權(quán)限認(rèn)證測(cè)試接口
               * @param request
               * @return
               */

              @RequestMapping("/teacher")
              public String teacher(HttpServletRequest request) {
                  return "success";
              }
          }

          這三個(gè)接口很簡(jiǎn)單,直接返回到指定頁(yè)面展示即可,只要認(rèn)證成功就會(huì)正常跳轉(zhuǎn),如果認(rèn)證失敗,就會(huì)跳轉(zhuǎn)到上文 ShrioConfig 中配置的頁(yè)面進(jìn)行展示。

          2.4.2 用戶(hù)登錄接口

          @Controller
          @RequestMapping("/user")
          public class UserController {

              /**
               * 用戶(hù)登錄接口
               * @param user user
               * @param request request
               * @return string
               */

              @PostMapping("/login")
              public String login(User user, HttpServletRequest request) {

                  // 根據(jù)用戶(hù)名和密碼創(chuàng)建token
                  UsernamePasswordToken token = new UsernamePasswordToken(user.getUsername(), user.getPassword());
                  // 獲取subject認(rèn)證主體
                  Subject subject = SecurityUtils.getSubject();
                  try{
                      // 開(kāi)始認(rèn)證,這一步會(huì)跳到我們自定義的realm中
                      subject.login(token);
                      request.getSession().setAttribute("user", user);
                      return "success";
                  }catch(Exception e){
                      e.printStackTrace();
                      request.getSession().setAttribute("user", user);
                      request.setAttribute("error""用戶(hù)名或密碼錯(cuò)誤!");
                      return "login";
                  }
              }
          }

          我們重點(diǎn)分析一下這個(gè)登錄接口,首先會(huì)根據(jù)前端傳過(guò)來(lái)的用戶(hù)名和密碼,創(chuàng)建一個(gè) token,然后使用 SecurityUtils 來(lái)創(chuàng)建一個(gè)認(rèn)證主體,接下來(lái)開(kāi)始調(diào)用 subject.login(token) 開(kāi)始進(jìn)行身份認(rèn)證了,注意這里傳了剛剛創(chuàng)建的 token,就如注釋中所述,這一步會(huì)跳轉(zhuǎn)到我們自定義的 realm 中,進(jìn)入 doGetAuthenticationInfo 方法,所以到這里,您就會(huì)明白該方法中那個(gè)參數(shù) token 了。然后就是上文分析的那樣,開(kāi)始進(jìn)行身份認(rèn)證。

          2.4.3 測(cè)試一下

          最后,啟動(dòng)項(xiàng)目,測(cè)試一下:瀏覽器請(qǐng)求 http://localhost:8080/user/admin 會(huì)進(jìn)行身份認(rèn)證,因?yàn)榇藭r(shí)未登錄,所以會(huì)跳轉(zhuǎn)到 IndexController 中的 /login 接口,然后跳轉(zhuǎn)到 login.html 頁(yè)面讓我們登錄,使用用戶(hù)名密碼為 csdn1/123456 登錄之后,我們?cè)跒g覽器中請(qǐng)求 http://localhost:8080/user/student 接口,會(huì)進(jìn)行角色認(rèn)證,因?yàn)閿?shù)據(jù)庫(kù)中 csdn1 的用戶(hù)角色是 admin,所以和配置中的吻合,認(rèn)證通過(guò);我們?cè)僬?qǐng)求 http://localhost:8080/user/teacher 接口,會(huì)進(jìn)行權(quán)限認(rèn)證,因?yàn)閿?shù)據(jù)庫(kù)中 csdn1 的用戶(hù)權(quán)限為 user:*,滿(mǎn)足配置中的 user:create,所以認(rèn)證通過(guò)。

          接下來(lái),我們點(diǎn)退出,系統(tǒng)會(huì)注銷(xiāo)重新讓我們登錄,我們使用 csdn2 這個(gè)用戶(hù)來(lái)登錄,重復(fù)上述操作,當(dāng)在進(jìn)行角色認(rèn)證和權(quán)限認(rèn)證這兩步時(shí),就認(rèn)證不通過(guò)了,因?yàn)閿?shù)據(jù)庫(kù)中 csdn2 這個(gè)用戶(hù)存的角色和權(quán)限與配置中的不同,所以認(rèn)證不通過(guò)。

          3. 總結(jié)

          本節(jié)主要介紹了 Shiro 安全框架與 Spring Boot 的整合。先介紹了 Shiro 的三大核心組件已經(jīng)它們的作用;然后介紹了 Shiro 的身份認(rèn)證、角色認(rèn)證和權(quán)限認(rèn)證;最后結(jié)合代碼,詳細(xì)介紹了 Spring Boot 中是如何整合 Shiro 的,并設(shè)計(jì)了一套測(cè)試流程,逐步分析 Shiro 的工作流程和原理,讓讀者更直觀地體會(huì)出 Shiro 的整套工作流程。Shiro 使用的很廣泛,希望讀者將其掌握,并能運(yùn)用到實(shí)際項(xiàng)目中。

          -End-

          最近有一些小伙伴,讓我?guī)兔φ乙恍?nbsp;面試題 資料,于是我翻遍了收藏的 5T 資料后,匯總整理出來(lái),可以說(shuō)是程序員面試必備!所有資料都整理到網(wǎng)盤(pán)了,歡迎下載!

          點(diǎn)擊??卡片,關(guān)注后回復(fù)【面試題】即可獲取

          在看點(diǎn)這里好文分享給更多人↓↓

          瀏覽 11
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  欧洲性爱无码 | 婷婷丁香伊人 | 91香蕉视频1区 | 久久久久久少妇 | 日韩AV乱伦|