0


一个Java的权限框架-Shiro

🏇

        S 
       
      
        h 
       
      
        i 
       
      
        r 
       
      
        o 
       
      
     
    
      \textcolor{Orange}{Shiro} 
     
    
  Shiro

🙏

       学 
      
     
       习 
      
     
       过 
      
     
       程 
      
     
       中 
      
     
       的 
      
     
       笔 
      
     
       记 
      
     
       , 
      
     
       方 
      
     
       便 
      
     
       查 
      
     
       阅 
      
     
       学 
      
     
       习 
      
     
    
   
     \textcolor{green}{学习过程中的笔记,方便查阅学习} 
    
   
 学习过程中的笔记,方便查阅学习💗

🍣

       笔 
      
     
       记 
      
     
       总 
      
     
       结 
      
     
       来 
      
     
       源 
      
     
       于 
      
     
       视 
      
     
       频 
      
     
       B 
      
     
       站 
      
     
       狂 
      
     
       神 
      
     
       说 
      
     
    
   
     \textcolor{green}{笔记总结来源于视频B站狂神说} 
    
   
 笔记总结来源于视频B站狂神说🍣

欢迎各位小伙伴😄关注👍点赞⭐️收藏📝留言

Shiro

1.shiro简介

  • Apach Shiro是一个Java的安全(权限)框架
  • 可以非常容易的开发出足够好的应用,其不仅可以用在javaSE环境,也可以用在JavaEE环境
  • 可以完成认证、授权、加密、会话管理,web集成,缓存等。
  • 官网:https://shiro.apache.org/> 在这里插入图片描述
  • 点击download,可以直接下载。也可以直接依赖包github地址:https://github.com/apache/shiro

功能

在这里插入图片描述

  • Authentication:身份认证、登录、验证用户是不是拥有相应的身份;
  • Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限,即判断用户能否进行什么操作,如:验证某个用户是否拥有某个角色,或者细粒度的验证某个用户对某个资源是否具有某个权限。
  • Session Manager:会话管理,即用户登录后就是第一次会话,在没有退出之前,它的所有信息都在会话中,会话可以是普通的javaSE环境,也可以是Web环境;
  • Cryptography:加密,保护数据的安全性,如密码加密存储到数据库中,而不是明文存储;
  • Web Support:Web支持,可以非常容易的集成到Web环境;
  • Caching:缓存,比如用户登录后,其用户信息,拥有的角色、权限不必每次去查,这样可以提高效率
  • Concurrency:Shiro支持多线程应用的并发验证,即,如在一个线程中开启另一个线程,能把权限自动的传播过去。
  • Testing:提供测试支持;
  • Run as:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问
  • Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话就不用的登录了。

shiro架构(外部)

在这里插入图片描述

  • subject:应用代码直接交互的对象是Subject,也就是说Shiro的对外API核心就是Subject,Subject代表了当前的用户,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是subject,如网络爬虫,机器人等,与subject的所有交互都会委托给SecurityManager;subject其实是一个门面,SecurityManager才是实际的执行者。
  • securityManager:安全管理器,即所有与安全有关的操作都会与SecurityManager交互,并且它管理着所有的subject,可以看出它是shiro的核心,它负责与Shiro的其他组件进行交互,它相当于SPringMVC的DispatcherServlet的角色。
  • Realm:Shiro从Realm获取安全数据(如用户,角色,权限),就是说SecurityManager要验证用户身份,那么它需要从Realm获取相应的用户进行比较,来确定用户的身份是否合法;也需要从Realm得到用户相应的角色,权限,进行验证用户的操作是否能够进行,可以把Realm看成dataSource;

shiro架构(内部)

在这里插入图片描述

  • subject:任何可以与应用交互的”用户“
  • SecurityManager:相当于SpringMVC中的DispatcherServet;是shiro的心脏,所有具体的交互都通过SecurityManager进行控制,它管理着所有的Subject,且负责进行认证,授权,会话及缓存的管理。
  • Authenticator:负责Subject认证,是一个扩展点,可以自定义实现;可以使用认证策略,即什么情况下算用户认证通过了;
  • Authorizer:授权器,即访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能;
  • Realm:可以有一个或者多个的realm,可以认为是安全实体数据源,即用于获取安全实体的,可以用JDBC实现,也可以是内存实现等等,由用户提供;所以一般在应用中都需要实现自己的realm
  • SessionManager:管理Session生命周期的组件,而Shiro并不仅仅可以用在web环境,也可以用在普通的JavaSE环境中
  • CacheManager:缓存控制器,来管理如用户、角色,权限等缓存的;因为这些数据基本上很少改变,放到缓存中可以提高访问的性能;
  • Cryptography:密码模块,Shiro提高了一些常见的加密组件用于密码加密,解密等

2.快速实践

十分钟入门官网:https://shiro.apache.org/tutorial.html

  • 首先创建一个普通的Maven项目。
  • 为了后续的方便,我们可以将src删除,然后创建一个module:hello-shiro。
  • 接下来我们先看依赖。https://github.com/apache/shiro/blob/main/samples/quickstart/pom.xml我们可以在里面看到我们需要的依赖,然后我们可以依赖再在https://shiro.apache.org/download.html#180官网这里找到对应的版本号,直接加进去。- 再一个简单的办法直接看10分钟入门https://shiro.apache.org/tutorial.html。这里注意把范围去掉,官网是test,非test环境是不能用的。```<dependencies><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.8.0</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>slf4j-simple</artifactId><version>1.7.21</version></dependency><dependency><groupId>org.slf4j</groupId><artifactId>jcl-over-slf4j</artifactId><version>1.7.21</version></dependency><dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency></dependencies>```
  • 然后再返回去查看配置文件在resources下- 创建log4j2.xml``````<!-- ~ Licensed to the Apache Software Foundation (ASF) under one ~ or more contributor license agreements. See the NOTICE file ~ distributed with this work for additional information ~ regarding copyright ownership. The ASF licenses this file ~ to you under the Apache License, Version 2.0 (the ~ "License"); you may not use this file except in compliance ~ with the License. You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, ~ software distributed under the License is distributed on an ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ~ KIND, either express or implied. See the License for the ~ specific language governing permissions and limitations ~ under the License. --><Configurationname="ConfigTest"status="ERROR"monitorInterval="5"><!-- ~ Licensed to the Apache Software Foundation (ASF) under one ~ or more contributor license agreements. See the NOTICE file ~ distributed with this work for additional information ~ regarding copyright ownership. The ASF licenses this file ~ to you under the Apache License, Version 2.0 (the ~ "License"); you may not use this file except in compliance ~ with the License. You may obtain a copy of the License at ~ ~ http://www.apache.org/licenses/LICENSE-2.0 ~ ~ Unless required by applicable law or agreed to in writing, ~ software distributed under the License is distributed on an ~ "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY ~ KIND, either express or implied. See the License for the ~ specific language governing permissions and limitations ~ under the License. --><Appenders><Consolename="Console"target="SYSTEM_OUT"><PatternLayoutpattern="%d{HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n"/></Console></Appenders><Loggers><Loggername="org.springframework"level="warn"additivity="false"><AppenderRefref="Console"/></Logger><Loggername="org.apache"level="warn"additivity="false"><AppenderRefref="Console"/></Logger><Loggername="net.sf.ehcache"level="warn"additivity="false"><AppenderRefref="Console"/></Logger><Loggername="org.apache.shiro.util.ThreadContext"level="warn"additivity="false"><AppenderRefref="Console"/></Logger><Rootlevel="info"><AppenderRefref="Console"/></Root></Loggers></Configuration>- 在resources下创建shiro.ini是灰色的不要怕。这是因为没有下载插件。不下载也是可以用的。## Licensed to the Apache Software Foundation (ASF) under one# or more contributor license agreements. See the NOTICE file# distributed with this work for additional information# regarding copyright ownership. The ASF licenses this file# to you under the Apache License, Version 2.0 (the# "License"); you may not use this file except in compliance# with the License. You may obtain a copy of the License at## http://www.apache.org/licenses/LICENSE-2.0## Unless required by applicable law or agreed to in writing,# software distributed under the License is distributed on an# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY# KIND, either express or implied. See the License for the# specific language governing permissions and limitations# under the License.## =============================================================================# Quickstart INI Realm configuration## For those that might not understand the references in this file, the# definitions are all based on the classic Mel Brooks' film "Spaceballs". ;)# =============================================================================# -----------------------------------------------------------------------------# Users and their assigned roles## Each line conforms to the format defined in the# org.apache.shiro.realm.text.TextConfigurationRealm#setUserDefinitions JavaDoc# -----------------------------------------------------------------------------[users]# user 'root' with password 'secret' and the 'admin' roleroot = secret, admin# user 'guest' with the password 'guest' and the 'guest' roleguest = guest, guest# user 'presidentskroob' with password '12345' ("That's the same combination on# my luggage!!!" ;)), and role 'president'presidentskroob = 12345, president# user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'darkhelmet = ludicrousspeed, darklord, schwartz# user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'lonestarr = vespa, goodguy, schwartz# -----------------------------------------------------------------------------# Roles with assigned permissions## Each line conforms to the format defined in the# org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc# -----------------------------------------------------------------------------[roles]# 'admin' role has all permissions, indicated by the wildcard '*'admin = *# The 'schwartz' role can do anything (*) with any lightsaber:schwartz = lightsaber:*# The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with# license plate 'eagle5' (instance specific id)goodguy = winnebago:drive:eagle5
  • helloWorld在java目录下创建Qucikstart.java``````/* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information * regarding copyright ownership. The ASF licenses this file * to you under the Apache License, Version 2.0 (the * "License"); you may not use this file except in compliance * with the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, * software distributed under the License is distributed on an * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * KIND, either express or implied. See the License for the * specific language governing permissions and limitations * under the License. *//** * Simple Quickstart application showing how to use Shiro's API. * * @since 0.9 RC2 */importorg.apache.shiro.SecurityUtils;importorg.apache.shiro.authc.*;importorg.apache.shiro.config.IniSecurityManagerFactory;importorg.apache.shiro.mgt.SecurityManager;importorg.apache.shiro.session.Session;importorg.apache.shiro.subject.Subject;importorg.apache.shiro.util.Factory;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;publicclassQuickstart{privatestaticfinaltransientLogger log =LoggerFactory.getLogger(Quickstart.class);publicstaticvoidmain(String[] args){// The easiest way to create a Shiro SecurityManager with configured// realms, users, roles and permissions is to use the simple INI config.// We'll do that by using a factory that can ingest a .ini file and// return a SecurityManager instance:// Use the shiro.ini file at the root of the classpath// (file: and url: prefixes load from files and urls respectively):Factory<SecurityManager> factory =newIniSecurityManagerFactory("classpath:shiro.ini");SecurityManager securityManager = factory.getInstance();// for this simple example quickstart, make the SecurityManager// accessible as a JVM singleton. Most applications wouldn't do this// and instead rely on their container configuration or web.xml for// webapps. That is outside the scope of this simple quickstart, so// we'll just do the bare minimum so you can continue to get a feel// for things.SecurityUtils.setSecurityManager(securityManager);// Now that a simple Shiro environment is set up, let's see what you can do:// get the currently executing user:Subject currentUser =SecurityUtils.getSubject();// Do some stuff with a Session (no need for a web or EJB container!!!)Session session = currentUser.getSession(); session.setAttribute("someKey","aValue");String value =(String) session.getAttribute("someKey");if(value.equals("aValue")){ log.info("Retrieved the correct value! ["+ value +"]");}// let's login the current user so we can check against roles and permissions:if(!currentUser.isAuthenticated()){UsernamePasswordToken token =newUsernamePasswordToken("lonestarr","vespa"); token.setRememberMe(true);try{ currentUser.login(token);}catch(UnknownAccountException uae){ log.info("There is no user with username of "+ token.getPrincipal());}catch(IncorrectCredentialsException ice){ log.info("Password for account "+ token.getPrincipal()+" was incorrect!");}catch(LockedAccountException lae){ log.info("The account for username "+ token.getPrincipal()+" is locked. "+"Please contact your administrator to unlock it.");}// ... catch more exceptions here (maybe custom ones specific to your application?catch(AuthenticationException ae){//unexpected condition? error?}}//say who they are://print their identifying principal (in this case, a username): log.info("User ["+ currentUser.getPrincipal()+"] logged in successfully.");//test a role:if(currentUser.hasRole("schwartz")){ log.info("May the Schwartz be with you!");}else{ log.info("Hello, mere mortal.");}//test a typed permission (not instance-level)if(currentUser.isPermitted("lightsaber:wield")){ log.info("You may use a lightsaber ring. Use it wisely.");}else{ log.info("Sorry, lightsaber rings are for schwartz masters only.");}//a (very powerful) Instance Level permission:if(currentUser.isPermitted("winnebago:drive:eagle5")){ log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. "+"Here are the keys - have fun!");}else{ log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!");}//all done - log out! currentUser.logout();System.exit(0);}}
  • 运行测试> 在这里插入图片描述> 出现这个问题是没有一个依赖> > > <dependency><groupId>commons-logging</groupId><artifactId>commons-logging</artifactId><version>1.2</version></dependency>> > 在这里插入图片描述> 这个问题是由于依赖的范围有问题,需要把test删除> 完美结果> > 在这里插入图片描述
  • 主要方法//获取当前的用户对象 SubjectSubject currentUser =SecurityUtils.getSubject();//通过当前用户拿到sessionSession session = currentUser.getSession();//判断当前的用户是否被认证currentUser.isAuthenticated()//获取存储的principalcurrentUser.getPrincipal()//设置角色currentUser.hasRole("schwartz")//粗粒度currentUser.isPermitted("lightsaber:wield"))//细粒度currentUser.isPermitted("winnebago:drive:eagle5")//注销currentUser.logout();

3.SpringBoot整合Shiro环境搭建

  1. 创建spring项目,勾选springweb和thymeleaf
  2. 测试基础环境- 在templates下创建index.html,并将命名空间及标签写入。<!DOCTYPEhtml><htmllang="en"xmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>Title</title></head><body>首页<pth:text="${msg}"></p></body></html>- 创建controller``````packagecom.hxl.controller;importorg.springframework.stereotype.Controller;importorg.springframework.ui.Model;importorg.springframework.web.bind.annotation.RequestMapping;@ControllerpublicclassMyController{@RequestMapping({"/","/index"})publicStringtoIndex(Model model){ model.addAttribute("msg","hello,Shiro");return"index";}}- 启动测试,出现下述则表示环境搭好了在这里插入图片描述
  3. 整合Shiro- 导入依赖包<!-- subject : 用户 securityManager:管理所有用户 realm:连接数据--><!--导入Shiro,shiro整合spring的包--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.7.1</version></dependency>- 编写配置类创建config的包进行编写- 编写ShiroConfigpackagecom.hxl.config;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassShiroConfig{/*下面三个对应的三大核心对象,配的时候倒着配,先创建对象,在接管,后连到前端*///ShiroFilterFactoryBean//DefaultWebSecurityManager//创建realm对象;需要自定义类}- 编写我们的自定义类packagecom.hxl.config;importorg.apache.shiro.authc.AuthenticationException;importorg.apache.shiro.authc.AuthenticationInfo;importorg.apache.shiro.authc.AuthenticationToken;importorg.apache.shiro.authz.AuthorizationInfo;importorg.apache.shiro.realm.AuthorizingRealm;importorg.apache.shiro.subject.PrincipalCollection;//自定义的UserRealm ,需要继承AuthorizingRealmpublicclassUserRealmextendsAuthorizingRealm{//授权@OverrideprotectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollection principalCollection){System.out.println("执行了=》授权doGetAuthorizationInfo");returnnull;}//认证@OverrideprotectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationToken authenticationToken)throwsAuthenticationException{System.out.println("执行了=》认证doGetAuthorizationInfo");returnnull;}}- 定义完之后就可以用了packagecom.hxl.config;importorg.apache.catalina.User;importorg.apache.shiro.spring.web.ShiroFilterFactoryBean;importorg.apache.shiro.web.mgt.DefaultWebSecurityManager;importorg.springframework.beans.factory.annotation.Qualifier;importorg.springframework.context.annotation.Bean;importorg.springframework.context.annotation.Configuration;@ConfigurationpublicclassShiroConfig{/*下面三个对应的三大核心对象,配的时候倒着配,先创建对象,在接管,后连到前端*///ShiroFilterFactoryBean:3/*这里同样可以使用之前的方法,在DefaultWebSecurityManager前加@Qualifier("方法名") * 但是名字太长了,所以还可以使用另外一种方式进行绑定,这就需要修改DefaultWebSecurityManager这个的Bean。添加别名 * */@BeanpublicShiroFilterFactoryBeangetShiroFilterFactoryBean(@Qualifier("securityManger")DefaultWebSecurityManager defaultWebSecurityManager){ShiroFilterFactoryBean bean =newShiroFilterFactoryBean();//设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager);return bean;}//DefaultWebSecurityManager:2/*public DefaultWebSecurityManager getDefaultWebSecurityManager(UserRealm userRealm){ 这个没有把下面的方法绑定过来 */@Bean(name ="securityManger")publicDefaultWebSecurityManagergetDefaultWebSecurityManager(@Qualifier("userRealm")UserRealm userRealm){DefaultWebSecurityManager securityManager =newDefaultWebSecurityManager();//关闭UserRealm securityManager.setRealm(userRealm);return securityManager;}//创建realm对象;需要自定义类:1@BeanpublicUserRealmuserRealm(){returnnewUserRealm();}//这个之后我们写的类就被spring托管了}- 增加页面在这里插入图片描述增加和更新页面仅作业测试页面先写上内容方便区分即可。在首页上增加可以跳转的连接<ath:href="@{/user/add}">add</a><ath:href="@{/user/update}">update</a>- controller中进行跳转@RequestMapping("/user/add")publicStringadd(){return"user/add";}@RequestMapping("/user/update")publicStringupdate(){return"user/update";}- 测试:能成功跳转即可。

4.实现登录拦截

  • 首先先增加一个登录页面,在templates目录下<!DOCTYPEhtml><htmllang="en"><head><metacharset="UTF-8"><title>登录</title></head><body><formaction=""><p>用户名:<inputtype="text"name="username"></p><p>密码:<inputtype="text"name="password"></p><p><inputtype="submit"></p></form></body></html>
  • controller中增加请求@RequestMapping("/toLogin")publicStringtoLogin(){return"login";}
  • 在ShiroConfig中添加@BeanpublicShiroFilterFactoryBeangetShiroFilterFactoryBean(@Qualifier("securityManger")DefaultWebSecurityManager defaultWebSecurityManager){ShiroFilterFactoryBean bean =newShiroFilterFactoryBean();//设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager);//添加shiro的内置过滤器/* * anon:无需认证就可以访问 * authc:必须认证了才能访问 * user:必须拥有记住我功能才能用 * perms:拥有对某个资源的权限才能访问 * role:拥有某个角色权限才能访问 * */Map<String,String> filterMap =newLinkedHashMap<>(); filterMap.put("/user/add","authc"); filterMap.put("/user/update","authc"); bean.setFilterChainDefinitionMap(filterMap);//设置登录的请求 bean.setLoginUrl("/toLogin");return bean;}

5.实现用户验证

  1. 在controller中增加请求@RequestMapping("/login")publicStringlogin(String username,String password){//获取当前的用户Subject subject =SecurityUtils.getSubject();//封装用户的登录数据UsernamePasswordToken token =newUsernamePasswordToken(username, password);}注意还没结束呢,我们这里有了请求,那么在前端就需要提交请求
  2. login.html这里的action``````<!DOCTYPEhtml><htmllang="en"xmlns:th="http://www.thymeleaf.org"><head><metacharset="UTF-8"><title>登录</title></head><body><formth:action="@{/login}"><p>用户名:<inputtype="text"name="username"></p><p>密码:<inputtype="text"name="password"></p><p><inputtype="submit"></p></form></body></html>
  3. 有了令牌该怎么办呢,可以看一下Quickstart。里面是怎么弄得在这里插入图片描述
  4. 那么就可以在我们的controller中添加@RequestMapping("/login")public String login(String username, String password, Model model){ //获取当前的用户 Subject subject = SecurityUtils.getSubject(); //封装用户的登录数据 UsernamePasswordToken token = new UsernamePasswordToken(username, password); try{ subject.login(token); //执行了登录的方法,如果没有异常就说明ok return "index"; }catch(UnknownAccountException e){ model.addAttribute("msg","用户名错误"); return "login"; }catch (IncorrectCredentialsException e){ model.addAttribute("msg","密码错误"); return "login"; }}有了提示信息,前端再把提示信息加上<pth:text="${msg}"style="color: red"></p>
  5. 那么前端传过来的数据和数据库中的数据怎么判断呢?这就需要在UserRealm里面进行认证//认证@OverrideprotectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationToken authenticationToken)throwsAuthenticationException{System.out.println("执行了=》认证doGetAuthorizationInfo");//数据库中取,用户名和密码String name ="root";String password ="123456";UsernamePasswordToken userToken =(UsernamePasswordToken) authenticationToken;if(!userToken.getUsername().equals(name)){returnnull;//抛出异常:UnknownAccountException}//密码认证,shiro做returnnewSimpleAuthenticationInfo("",password,"");}
  6. 测试> 在这里插入图片描述> 在这里插入图片描述> 在这里插入图片描述> 在这里插入图片描述> 登录成功后,一切都可以访问了。

6.整合Mybaits

  1. 先导入依赖除了之前的依赖还需要下面这些。<dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.mybatis.spring.boot</groupId><artifactId>mybatis-spring-boot-starter</artifactId><version>2.2.1</version></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency><dependency><groupId>log4j</groupId><artifactId>log4j</artifactId><version>1.2.17</version></dependency><dependency><groupId>com.alibaba</groupId><artifactId>druid</artifactId><version>1.2.8</version></dependency>
  2. 配置文件ymlspring:datasource:username: root password:123456url: jdbc:mysql://localhost:3306/jdbc?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8driver-class-name: com.mysql.cj.jdbc.Driver# 整合mybatismybatis:type-aliases-package: com.hxl.pojo mapper-locations: classpath:mapper/*.xml
  3. 创建resources/mapper。这个文件夹
  4. 创建pojomapperservice层并写入packagecom.hxl.pojo;importlombok.AllArgsConstructor;importlombok.Data;importlombok.NoArgsConstructor;importjava.sql.Date;@Data@AllArgsConstructor@NoArgsConstructorpublicclassUser{privateint id;privateString name;privateString password;privateString email;privateDate birthday;}``````packagecom.hxl.mapper;importcom.hxl.pojo.User;importorg.apache.ibatis.annotations.Mapper;importorg.springframework.stereotype.Repository;//这个注解表示本类是一个mybatis的mapper类@Mapper@Repository//注解是将接口的一个实现类交给spring管理。publicinterfaceUserMapper{//通过名字获取publicUserqueryByName(String name);}``````package com.hxl.service;import com.hxl.pojo.User;public interface UserService { public User queryByName(String name);}``````packagecom.hxl.service;importcom.hxl.mapper.UserMapper;importcom.hxl.pojo.User;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.stereotype.Service;@ServicepublicclassUserServiceImplimplementsUserService{@AutowiredUserMapper userMapper;@OverridepublicUserqueryByName(String name){return userMapper.queryByName(name);}}
  5. 把resources/mapper补上<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPEmapperPUBLIC"-//mybatis.org//DTD Mapper 3.0//EN""http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mappernamespace="com.hxl.mapper.UserMapper"><selectid="queryByName"parameterType="String"resultType="User"> select * from users where name = #{name} </select></mapper>
  6. 测试在测试类中编写packagecom.hxl;importcom.hxl.service.UserServiceImpl;importorg.junit.jupiter.api.Test;importorg.springframework.beans.factory.annotation.Autowired;importorg.springframework.boot.test.context.SpringBootTest;@SpringBootTestclassShiroSpringbootApplicationTests{@AutowiredUserServiceImpl userService;@TestvoidcontextLoads(){System.out.println(userService.queryByName("老大"));}}
  7. 查看输出在这里插入图片描述
  8. 遇到的问题:如果遇到If you want an embedded database (H2, HSQL or Derby), please put it on the c资源过滤以及数据库配置没有生效问题。把它放在build中<resources><resource><directory>src/main/java</directory><includes><include>**/*.xml</include><include>**/*.yml</include></includes><filtering>true</filtering></resource><resource><directory>src/main/resources</directory><includes><include>**/*.xml</include><include>**/*.yml</include></includes><filtering>true</filtering></resource></resources>
  9. 真实的人进行登录拦截@AutowiredUserService userService;//认证@OverrideprotectedAuthenticationInfodoGetAuthenticationInfo(AuthenticationToken authenticationToken)throwsAuthenticationException{System.out.println("执行了=》认证doGetAuthorizationInfo");UsernamePasswordToken token =(UsernamePasswordToken) authenticationToken;//连接真实的数据库User user = userService.queryByName(token.getUsername());if(user ==null){//没有这个人returnnull;//会报出异常}//密码认证,shiro做,密码加密了returnnewSimpleAuthenticationInfo("",user.getPassword(),"");}

请求授权实现

当一个人没有某操作的功能权限,是不能进入的。那么应该怎么实现呢?

在ShiroConfig中进行编写

在这里插入图片描述

//授权:正常情况下,没有授权会跳转到未授权页面。
filterMap.put("/user/add","perms[user:add]");
filterMap.put("/user/update","perms[user:update]");

bean.setFilterChainDefinitionMap(filterMap);//设置未授权页面
bean.setUnauthorizedUrl("/noauth");

同时在controller中增加一个请求

@RequestMapping("/noauth")@ResponseBodypublicStringnoauth(){return"未经授权不能操作";}

此时只是简单的实现。而更完善的需要在UserRealm中实现

在这里插入图片描述

同时需要在数据库中增加一列,用户的权限

在这里插入图片描述

给root用户增加一个add权限

在这里插入图片描述

这个时候就需要把pojo类里面也增加上字段perms

最后在授权的

UserRealm
//授权@OverrideprotectedAuthorizationInfodoGetAuthorizationInfo(PrincipalCollection principalCollection){System.out.println("执行了=》授权doGetAuthorizationInfo");SimpleAuthorizationInfo info =newSimpleAuthorizationInfo();
    info.addStringPermission("user:add");//拿到当前登录的这个对象Subject subject =SecurityUtils.getSubject();User principal =(User) subject.getPrincipal();//拿到User对象//设置当前用户的权限
    info.addStringPermission(principal.getPerms());returnnull;}

shiro整合thymeleaf

下载依赖包

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

在shiroConfig中编写

//整合ShiroDialect:用来整合shiro和thymeleafpublicShiroDialectgetShiroDialect(){returnnewShiroDialect();}

修改首页

<!DOCTYPEhtml><htmllang="en"xmlns:th="http://www.thymeleaf.org"xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"><head><metacharset="UTF-8"><title>Title</title></head><body>
首页

<p><ath:href="@{/toLogin}">登录</a></p><pth:text="${msg}"></p><divshiro:hasPermission="'user:add'"><ath:href="@{/user/add}">add</a></div><divshiro:hasPermission="'user:update'"><ath:href="@{/user/update}">update</a></div></body></html>

测试:

这样之后,登录用户不同显示不同,如果权限只有add,那么只会显示add

如果显示两个add,那么是之前授权的时候有一段代码

info.addStringPermission("user:add");

注释掉即可

发现登录成功之后还有登录按钮。需要在登录外面的p标签外包一个

<shiro:guest></shiro:guest>

在这里插入图片描述


本文转载自: https://blog.csdn.net/qq_43585922/article/details/125271373
版权归原作者 秦 羽 所有, 如有侵权,请联系我们删除。

“一个Java的权限框架-Shiro”的评论:

还没有评论