Spring Boot与Shiro和Mybatis整合
1:shiro是什么?
- Apache Shiro 是ASF旗下的一款开源软件
- shrio是一款强大而灵活的安全框架
- 可为任何应用提供安全保障— 从命令行应用、移动应用到大型网络及企业应用
2:shiro的四大基石:
- 认证(Authentication):用户身份识别。有时可看作为“登录”,它是用户证明自己是谁的一个行为。
- 授权(Authorization):访问控制过程,好比决定“认证谁” 可以访问它”。
- 会话管理(SessionManagement):管理用户的会话,甚至在没有WEB或EJB容器的环境中。管理用户与时间相关的状态。
- 加密(Cryptography):使用加密算法保护数据更加安全,防止数据被偷窥。
- 但此外还有一些附加的功能进行支持和加强比如:
- Web支持:利用Shiro的web支持API可以很容易地实现web程序安全;
- shiro支持并发
3:介绍完shiro了 让我们开始搭建第一个shiro项目吧
- 创建一个spring boot项目导入maven依赖:
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
导入maven环境之后 写一个:UserRealm类来继承AuthorizingRealm并重写它的两个方法
public class UserRealm extends AuthorizingRealm { @Override //授权方法 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("doGetAuthorizationInfo授权方法执行了"); return null; } //认证方法 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("doGetAuthenticationInfo认证方法执行了"); return null; } }
重写方法之后配置shiro的配置类:ShrioComfig:
@Configuration public class ShrioComfig { //第三步: @Bean public ShiroFilterFactoryBean Bean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); bean.setSecurityManager(defaultWebSecurityManager); Map<String,String>map=new LinkedHashMap(); map.put("/user/update","authc"); map.put("/user/add","authc"); bean.setFilterChainDefinitionMap(map); //设置如果拦截则切换到登录页面 bean.setLoginUrl("/login"); return bean; } //第二步:DefaultWebSecurityManager @Bean public DefaultWebSecurityManager defaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){ DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager(); defaultWebSecurityManager.setRealm(userRealm); return defaultWebSecurityManager; } //第一步:创造realm对象 需要自定义类 @Bean public UserRealm userRealm(){ return new UserRealm(); } }
然后再写一个控制层:MyController:
@Controller public class MyController { @RequestMapping({"/","/index"}) public String toIndex(Model model){ model.addAttribute("msg","hello Shrio!"); return "index"; } @RequestMapping("/user/add") public String goadd(){ return "/user/add"; } @RequestMapping("/user/update") public String update() { return "/user/update"; }
在templates包中写一个首页(index)页面:
<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>首页</h1> <p th:text="${msg}"></p> <a th:href="@{/user/add}">add</a> <a th:href="@{/user/update}">update</a> </body> </html>
在templates中添加一个user包然后写两个add和update页面:
add:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>add</h1> </body> </html>
update:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>update</h1> </body> </html>
开启测试:如果点进链接可以进去
那么我们的第一个shiro项目就完成了
那么我们开启进阶的第一步把 spring boot整合shiro和mybatis
第一步导入依赖:
<dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid</artifactId> <version>1.2.4</version> </dependency> <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.1.4</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency>
配置application.yaml文件和application.properties:
application.properties:
mybatis.type-aliases-package=com.kuang.pojo
application.yaml:
spring: datasource: username: root password: 5825600 #填写你的mysql密码和账户 #?serverTimezone=UTC解决时区的报错 url: jdbc:mysql://localhost:3306/luyunjie?useSSL=false&useUnicode=false&characterEncoding=UTF-8&serverTimezone=UTC driver-class-name: com.mysql.cj.jdbc.Driver type: com.alibaba.druid.pool.DruidDataSource #Spring Boot 默认是不注入这些属性值的,需要自己绑定 #druid 数据源专有配置 initialSize: 5 minIdle: 5 maxActive: 20 maxWait: 60000 timeBetweenEvictionRunsMillis: 60000 minEvictableIdleTimeMillis: 300000 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false poolPreparedStatements: true #配置监控统计拦截的filters,stat:监控统计、log4j:日志记录、wall:防御sql注入 #如果允许时报错 java.lang.ClassNotFoundException: org.apache.log4j.Priority #则导入 log4j 依赖即可,Maven 地址:https://mvnrepository.com/artifact/log4j/log4j filters: stat,wall,log4j maxPoolPreparedStatementPerConnectionSize: 20 useGlobalDataSourceStat: true connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
配置完环境 我们配置mybatis的实现类User:
属性跟你的mysql数据库的字段对应
@Data @AllArgsConstructor @NoArgsConstructor public class User { private int id; private String loginName; private String loginPwd; }
写出UserMapper接口:
@Repository @Mapper public interface UserMapper { @Select("select * from t_user where loginName=#{loginName}") //不建议用注解 因为有些情况太复杂的sql编写不了 public User getuser(String loginName); }
再写一个业务层UserSverice:
public interface UserService { public User getuser(String loginName); }
再写UserSverice的实现类:
@Service public class UserServiceImp implements UserService { @Autowired UserMapper userMapper; @Override public User getuser(String loginName) { return userMapper.getuser(loginName); } }
去ShrioApplicationTests测试类一下:
@SpringBootTest
class ShrioApplicationTests {
@Autowired
UserServiceImp userServiceImp;
@Test
void contextLoads() {
System.out.println(userServiceImp.getuser("lyj"));
}
}
如果可以查询到数据库数据就证明你的环境配好了:
那么我们的可以去进行连接数据库的操作了
来提个要求 如果没有登录点击add和update就要登录才能进入:
第一步:
在MyController中添加一个返回登录页面的和获得当前用户并封装和返回异常的方法:
@RequestMapping("/login") public String login() { return "/login"; } @RequestMapping("/tologin") public String login(String username,String password,Model model) { //获取当前的用户 Subject subject = SecurityUtils.getSubject(); //封装当前用户的数据 UsernamePasswordToken user=new UsernamePasswordToken(username,password); try{ subject.login(user); return "index"; }catch (UnknownAccountException e){ model.addAttribute("msg","账户错误"); return "login"; }catch (IncorrectCredentialsException e){ model.addAttribute("msg","密码错误"); return "login"; } }
第二步:
在templates写出一个登录(login)页面:
<!DOCTYPE html> <html lang="en"xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>登录</h1> <br> <p th:text="${msg}" style="color: red;"></p> <form th:action="@{/tologin}"> <p>用户<input type="text" name="username" ></p> <p>密码<input type="text" name="password" ></p> <p><input type="submit"></p> </form> </body> </html>
第三步:
去我们的UserRealm类中完善方法:
public class UserRealm extends AuthorizingRealm { @Autowired UserServiceImp userServiceImp; @Override//授权方法 protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { System.out.println("doGetAuthorizationInfo授权方法执行了"); return null; } //认证方法 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { System.out.println("doGetAuthenticationInfo认证方法执行了"); UsernamePasswordToken user= (UsernamePasswordToken) authenticationToken; //获得密码 User getuser = userServiceImp.getuser(user.getUsername()); if (getuser==null){ return null;
//返回null就自动提式用户错误 } return new SimpleAuthenticationInfo("",getuser.getLoginPwd(),""); } }
第四步:
在ShrioComfig类中完善方法 设定如果没有登录就拦截:
//第三步:ShiroFilterFactoryBean @Bean public ShiroFilterFactoryBean Bean(@Qualifier("defaultWebSecurityManager") DefaultWebSecurityManager defaultWebSecurityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); bean.setSecurityManager(defaultWebSecurityManager); Map<String,String>map=new LinkedHashMap(); map.put("/user/update","authc"); map.put("/user/add","authc"); bean.setFilterChainDefinitionMap(map); //设置如果拦截则切换到登录页面 bean.setLoginUrl("/login"); return bean; }
第四步:
进行测试:如果登录成功则可访问add和update页面;
如果成功则可进入add和update页面 则测试成功!
这是shiro的一个小入门 以后会给大家带来更好的教程 小白努力学习的每一天