idea环境 springBoot 2.1.9 整合shiro mybatis
创建springBoot项目- pom.xml代码 . 这里我直接将mybatis等依赖也直接引入
1 <?xml version="1.0" encoding="UTF-8"?> 2 <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 3 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> 4 <modelVersion>4.0.0</modelVersion> 5 <parent> 6 <groupId>org.springframework.boot</groupId> 7 <artifactId>spring-boot-starter-parent</artifactId> 8 <version>2.1.9.RELEASE</version> 9 <relativePath/> <!-- lookup parent from repository --> 10 </parent> 11 <groupId>com</groupId> 12 <artifactId>demo</artifactId> 13 <version>0.0.1-SNAPSHOT</version> 14 <name>demo</name> 15 <description>Demo project for Spring Boot</description> 16 <!--jdk的环境--> 17 <properties> 18 <java.version>1.8</java.version> 19 </properties> 20 21 <dependencies> 22 <dependency> 23 <groupId>org.springframework.boot</groupId> 24 <artifactId>spring-boot-configuration-processor</artifactId> 25 <optional>true</optional> 26 </dependency> 27 <!--Lombok能以简单的注解形式来简化java代码,提高开发人员的开发效率--> 28 <dependency> 29 <groupId>org.projectlombok</groupId> 30 <artifactId>lombok</artifactId> 31 <optional>true</optional> 32 </dependency> 33 <!--热部署:当发现任何类发生了改变,就会通过 JVM 类加载的方式,加载最新的类到虚拟机中,这样就不需要重新启动也能看到修改后的效果了。--> 34 <dependency> 35 <groupId>org.springframework.boot</groupId> 36 <artifactId>spring-boot-devtools</artifactId> 37 <optional>true</optional> <!-- 这个需要为 true 热部署才有效 --> 38 </dependency> 39 40 <dependency> 41 <groupId>org.springframework.boot</groupId> 42 <artifactId>spring-boot-starter-web</artifactId> 43 </dependency> 44 <dependency> 45 <groupId>org.springframework.boot</groupId> 46 <artifactId>spring-boot-starter-test</artifactId> 47 <scope>test</scope> 48 </dependency> 49 50 <dependency> 51 <groupId>org.mybatis.spring.boot</groupId> 52 <artifactId>mybatis-spring-boot-starter</artifactId> 53 <version>2.1.0</version> 54 </dependency> 55 <!--MyBatis逆向工程--> 56 <dependency> 57 <groupId>org.mybatis.generator</groupId> 58 <artifactId>mybatis-generator-core</artifactId> 59 <version>1.3.6</version> 60 </dependency> 61 <dependency> 62 <groupId>com.microsoft.sqlserver</groupId> 63 <artifactId>mssql-jdbc</artifactId> 64 <scope>runtime</scope> 65 </dependency> 66 <dependency> 67 <groupId>com.alibaba</groupId> 68 <artifactId>druid</artifactId> 69 <version>1.1.9</version> 70 </dependency> 71 <!-- StringUtils工具类 --> 72 <dependency> 73 <groupId>org.apache.commons</groupId> 74 <artifactId>commons-lang3</artifactId> 75 <version>3.4</version> 76 </dependency> 117 <dependency> 118 <groupId>org.apache.shiro</groupId> 119 <artifactId>shiro-spring</artifactId> 120 <version>1.3.2</version> 121 </dependency> 139 <!--thymeleaf 模板--> 140 <dependency> 141 <groupId>org.springframework.boot</groupId> 142 <artifactId>spring-boot-starter-thymeleaf</artifactId> 143 </dependency> 144 </dependencies> 145 146 <build> 147 <plugins> 148 <plugin> 149 <groupId>org.springframework.boot</groupId> 150 <artifactId>spring-boot-maven-plugin</artifactId> 151 </plugin> 152 </plugins> 153 </build> 154 155 </project>
2.spring的application.yml 配置
1 server: 2 port: 8080 3 spring: 4 datasource: 5 url: jdbc:sqlserver://192.168.xx.xx:1433;DatabaseName=xxx_test 6 driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver 7 username: xx 8 password: 123456 9 type: com.alibaba.druid.pool.DruidDataSource 10 # Druid连接池配置相关 11 druid: 12 # 初始大小,最大,最小 13 initial-size: 5 14 min-idle: 5 15 max-active: 20 16 # 配置获取连接等待超时的时间 17 max-wait: 60000 18 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 19 time-between-eviction-runs-millis: 60000 20 # 配置一个连接在池中最小生存的时间,单位是毫秒 21 min-evictable-idle-time-millis: 300000 43 mybatis: 44 type-aliases-package: com.demo.entity 45 # 驼峰命名 46 configuration: 47 map-underscore-to-camel-case: true 48 mapper-locations: classpath*:mapper/*.xml 49 logging: 50 level: 51 com.demo: debug
3.springBoot启动类
1 package com.demo; 2 3 import org.mybatis.spring.annotation.MapperScan; 4 import org.springframework.boot.SpringApplication; 5 import org.springframework.boot.autoconfigure.SpringBootApplication; 6 7 @SpringBootApplication 8 @MapperScan(basePackages = "com.demo.mapper") 9 public class Demo20191008Application { 10 11 public static void main(String[] args) { 12 13 SpringApplication.run(Demo20191008Application.class, args); 14 } 15 }
4.shiro的配置类
1 package com.demo.shiro; 2 3 import org.apache.shiro.spring.web.ShiroFilterFactoryBean; 4 import org.apache.shiro.web.mgt.DefaultWebSecurityManager; 5 import org.springframework.beans.factory.annotation.Qualifier; 6 import org.springframework.context.annotation.Bean; 7 import org.springframework.context.annotation.Configuration; 8 9 import java.util.LinkedHashMap; 10 import java.util.Map; 11 12 @Configuration 13 public class ShiroConfig { 14 15 /* 16 * 创建 ShiroFilterFactoryBean 17 * 18 */ 19 @Bean 20 public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){ 21 ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); 22 //1.设置安全管理器 23 shiroFilterFactoryBean.setSecurityManager(securityManager); 24 /** 25 * 2.添加shiro内置过滤器 26 * shiro内置过滤器,可以实现权限相关的拦截器 27 * 常用的过滤器: 28 * anon:无需认证(登录)可以访问 29 * authc:必须认证才可以访问 30 * user:如果使用remeberMe的功能才可以直接访问 31 * perms:该资源必须得到资源权限才可以访问 32 * role:该资源必须得到角色权限才可以访问 33 */ 34 Map<String,String> filterMap = new LinkedHashMap<String, String>(); 35 36 /** 37 * filterMap.put("/test/add","authc"); 38 * filterMap.put("/test/update","authc"); 39 */ 40 filterMap.put("/index/login","anon"); 41 filterMap.put("/index/*","authc"); 42 /** 43 * 当页面路径被拦截后 shiro会自动跳转到login.jsp页面 44 * 当然这里可以重新定义跳转的路径 45 */ 46 shiroFilterFactoryBean.setLoginUrl("/test/toLogin"); 47 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); 48 49 return shiroFilterFactoryBean; 50 } 51 52 /* 53 * 创建 DefaultWebSecurityManager 54 * @Qualifier 关联下方的 getRealm()返回的 MyRealm 55 * @Qualifier:限定描述符,用于细粒度选择候选者; 56 * @Qualifier注解的用处:当一个接口有多个实现的时候,为了指名具体调用哪个类的实现。 57 * @Qualifier限定哪个bean应该被自动注入。当Spring无法判断出哪个bean应该被注入时,@Qualifier注解有助于消除歧义bean的自动注入。 58 */ 59 @Bean(name = "securityManager") 60 public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("myRealm") MyRealm myRealm){ 61 DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); 62 //需要关联 Realm 63 securityManager.setRealm(myRealm); 64 return securityManager; 65 } 66 67 /* 68 * 创建 Realm 69 * @Bean的作用是将方法返回的对象放在spring中,方便别处使用 70 * 71 */ 72 @Bean(name = "myRealm") 73 public MyRealm getRealm(){ 74 return new MyRealm(); 75 } 76 }
5.自定义AuthorizingRealm的实现类
1 package com.demo.shiro; 2 3 import org.apache.shiro.authc.*; 4 import org.apache.shiro.authz.AuthorizationInfo; 5 import org.apache.shiro.realm.AuthorizingRealm; 6 import org.apache.shiro.subject.PrincipalCollection; 7 8 public class MyRealm extends AuthorizingRealm { 9 /** 10 * 执行授权的逻辑 11 * @param principalCollection 12 * @return 13 */ 14 @Override 15 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { 16 System.out.println("执行授权的逻辑"); 17 return null; 18 } 19 20 /** 21 * 执行授权的逻辑 22 * @param authenticationToken 23 * @return 24 * @throws AuthenticationException 25 */ 26 @Override 27 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { 28 /** 29 * 这里应该调用sql查询数据库对应信息,但是这里我先将数据写死 30 */ 31 String name = "权志龙"; 32 String password = "123456"; 33 /** 34 * authenticationToken 是由subject.login(token);传过来的参数 35 */ 36 UsernamePasswordToken token = (UsernamePasswordToken)authenticationToken; 37 /** 38 * 编写shiro判断逻辑 39 * 1,判断用户名 40 * 2,判断密码 41 */ 42 if(!token.getUsername().equals(name)){ 43 /** 44 * 如果没有当前用户,我们只需要return null;而shiro底层会抛出 UnknownAccountException异常 45 */ 46 return null; 47 } 48 return new SimpleAuthenticationInfo("",password,""); 49 } 50 }
6.Controller层
1 package com.demo.controller; 2 3 import org.apache.shiro.SecurityUtils; 4 import org.apache.shiro.authc.IncorrectCredentialsException; 5 import org.apache.shiro.authc.UnknownAccountException; 6 import org.apache.shiro.authc.UsernamePasswordToken; 7 import org.apache.shiro.subject.Subject; 8 import org.springframework.stereotype.Controller; 9 import org.springframework.ui.Model; 10 import org.springframework.web.bind.annotation.RequestMapping; 11 import org.springframework.web.bind.annotation.RequestParam; 12 import org.springframework.web.bind.annotation.ResponseBody; 13 import org.springframework.web.bind.annotation.RestController; 14 15 import java.security.Security; 16 17 @Controller 18 @RequestMapping(value = {"/index",""}) 19 public class IndexController { 20 21 @RequestMapping("/hello") 22 @ResponseBody 23 public String helloTest(){ 24 return "hello word"; 25 } 26 27 @RequestMapping("/testThymeleaf") 28 public String testThymeleaf(Model model){ 29 model.addAttribute("name","权志龙"); 30 return "test"; 31 } 32 @RequestMapping(value = {"/toLogin",""}) 33 public String toLogin(Model model){ 34 return "login"; 35 } 36 37 @RequestMapping("/login") 38 public String login(@RequestParam("name")String name , @RequestParam("password")String password, Model model){ 39 /** 40 * 使用shiro编写认证操作 41 */ 42 //1.获取 Subject 43 Subject subject = SecurityUtils.getSubject(); 44 45 //2.封装用户数据 46 UsernamePasswordToken token = new UsernamePasswordToken(name,password); 47 48 //执行登录方法 49 try { 50 /** 51 * 执行 subject.login(token); 这句话就会跳转到 MyRealm下定义的 doGetAuthenticationInfo方法 52 */ 53 subject.login(token); 54 /** 55 * 没有异常则表示登录成功 56 * 登录成功则跳转到 test.html页面 57 * 如果直接写 return "testThymeleaf";会默认testThymeleaf会是一个html页面 58 * 所以要重定向 return "redirect:/test/testThymeleaf"; 59 */ 60 return "redirect:/index/testThymeleaf"; 61 }catch (UnknownAccountException e){ 62 //抛出异常则登录失败 63 model.addAttribute("msg","用户名不存在"); 64 /** 65 * return "redirect:/toLogin"; 66 * 如果这里采用重定向直接跳转到login.html页面时 其中msg信息就不会被带到页面上去 67 * 所以这里采用直接跳页面 return "login"; 68 */ 69 return "login"; 70 }catch (IncorrectCredentialsException e){ 71 //抛出异常则登录失败 72 model.addAttribute("msg","密码错误"); 73 return "login"; 74 } 75 } 76 77 @RequestMapping("/add") 78 public String add(Model model){ 79 return "user/add"; 80 } 81 82 @RequestMapping("/update") 83 public String update(Model model){ 84 return "user/update"; 85 } 86 }
7.登录login.html
1 <!DOCTYPE html> 2 <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>登录</title> 6 </head> 7 <body> 8 <h3 th:text="${msg}" style="color: red;"></h3> 9 <form method="post" action="/index/login"> 10 用户名:<input type="text" name="name" /> <br/> 11 密码:<input type="password" name="password"/> 12 <input type="submit" value="登录"> 13 </form> 14 </body> 15 </html>
8.登录成功页面test.html ,添加页面add.html ,修改页面 update.html
1 <!DOCTYPE html> 2 <html lang="en" xmlns:th="http://www.w3.org/1999/xhtml"> 3 <head> 4 <meta charset="UTF-8"> 5 <title>Title</title> 6 </head> 7 <body> 8 <h3 th:text="${name}"></h3> 9 <hr> 10 进入用户的添加:<a href="/test/add">用户的添加</a><br> 11 进入用户的更新:<a href="/test/update">用户的更新</a><br> 12 </body> 13 </html> 14 15 <!DOCTYPE html> 16 <html lang="en"> 17 <head> 18 <meta charset="UTF-8"> 19 <title>用户的添加</title> 20 </head> 21 <body> 22 用户的添加页面 23 </body> 24 </html> 25 26 27 <!DOCTYPE html> 28 <html lang="en"> 29 <head> 30 <meta charset="UTF-8"> 31 <title>用户的更新</title> 32 </head> 33 <body> 34 用户的更新页面 35 </body> 36 </html>
最终效果
对应mapper的扫描@MapperScan(basePackages = "com.demo.mapper") 以及mapper.xml的扫描配置 mapper-locations: classpath*:mapper/*.xml,以及mabytis的配置都已写好,,所以配置好数据库相关信息,写好mapper.xml等即可实现连接数据库来配合shiro校验用户的功能
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?