1.导入依赖
主要添加shiro,springboot,thymeleaf,thymeleaf-shiro的依赖
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<!--
subject 用户
securityManager 管理所有用户
realm 连接用户
-->
<!-- shiro整合spring的包 -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.application.yml中配置数据连接和日志
- 配置thymeleaf的缓存为false
- 配置mybatis-plus的数据源
- 配置mybatis-plus的日志和逻辑删除
spring:
thymeleaf:
cache: false
datasource:
username: root
password: root
url: jdbc:mysql://localhost:33060/test?useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai
driver-class-name: com.mysql.cj.jdbc.Driver
# 配置mybatisplus
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl # 设置日志为控制台输出
# 配置逻辑删除
global-config:
db-config:
logic-delete-value: 1 # 删除的值为1
logic-not-delete-value: 0 # 不删除的值为0
3.编写配置类
3.1 MybatisPlusConfig类
- 乐观锁插件
- 分页插件
- 逻辑删除
- SQL执行效率插件
@Configuration //配置类
@MapperScan("com.kuang.mapper") //扫描mapper包
@EnableTransactionManagement //开启事务
public class MybatisPlusConfig {
//注册乐观锁插件
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
//分页插件
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
//逻辑删除
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
//SQL执行效率插件
@Bean
@Profile({"dev","test"})// 设置 dev test 环境开启
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(1000); //单位ms,设置最大执行时间,超时则不执行
performanceInterceptor.setFormat(true); //格式化SQL
return performanceInterceptor;
}
}
3.2 自定义UserRealm extends AuthorizingRealm
- 获取到用户,根据数据库中的权限信息对用户进行授权
- 登陆认证,判断是否有此用户
//自定义的UserRealm extends AuthorizingRealm
public class UserRealm extends AuthorizingRealm {
@Autowired
ShiroMapper shiroMapper; //shiro是数据库的表名,shiromapper是mapper文件,用于从数据库中查询用户
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("执行了授权");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//拿到当前的登陆对象
Shiro user = (Shiro)SecurityUtils.getSubject().getPrincipal();
//设置当前用户的权限
info.addStringPermission(user.getPerms());
return info;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行了认证");
UsernamePasswordToken userToken = (UsernamePasswordToken) token;
QueryWrapper<Shiro> wrapper = new QueryWrapper<>();
wrapper.eq("username",userToken.getUsername());
Shiro user = shiroMapper.selectOne(wrapper);
System.out.println(user);
if (null == user){
return null;
}
//密码认证,shiro做
return new SimpleAuthenticationInfo(user, user.getPassword(), "");
}
}
3.3 ShiroConfig类,项目页面的权限配置
这些配置方法上要添加@Bean 注解,将方法添加到spring容器中- 将自定义的userRealm配置到DefaultWebSecurityManager中
- 将DefaultWebSecurityManager配置到ShiroFilterFactoryBean中
- 对页面设置访问权限
/**
anno: 无需认证既可以访问
authc: 认证了才能访问
user: 必须拥有记住我才能用
perms: 拥有对某个资源的权限才能访问
role: 拥有某个角色权限才能访问
*/ - 设置登陆的请求URL: /toLogin
- 设置未授权的跳转URL : /unauthorized
- ShiroDialect: 用来整合shiro和thymeleaf
@Configuration
public class ShiroConfig {
//3.ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(defaultWebSecurityManager);
//添加shiro的内置过滤器
/**
anno: 无需认证既可以访问
authc: 认证了才能访问
user: 必须拥有记住我才能用
perms: 拥有对某个资源的权限才能访问
role: 拥有某个角色权限才能访问
*/
LinkedHashMap<String, String> filterMap = new LinkedHashMap<>();
filterMap.put("/user/add","perms[user:add]");
filterMap.put("/user/update","perms[user:update]");
filterMap.put("/user/*", "authc");
bean.setFilterChainDefinitionMap(filterMap);
//设置登陆的请求
bean.setLoginUrl("/toLogin");
//未授权页面
bean.setUnauthorizedUrl("/unauthorized");
return bean;
}
//2.DefaultWebSecurityManager
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联UserRealm
securityManager.setRealm(userRealm);
return securityManager;
}
//1.创建realm对象,需要自定义类
@Bean
public UserRealm userRealm() {
return new UserRealm();
}
//整合ShiroDialect: 用来整合shiro和thymeleaf
//package at.pollux.thymeleaf.shiro.dialect;
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
}
4.controller层配置登陆的设置
- 用户未登陆跳转到登陆URL: /toLogin
- /toLogin跳转到login.html页面进行登陆,经过/login验证
- /login的行为如下
创建一个token存储username,password
使用shiro的SecurityUtils.getSubject().login() 进行登陆
shiro会自动判断是用户名还是密码错误
如果没错就对用户进行认证,并存储到Principal中
@RequestMapping("/toLogin")
public String toLogin() {
return "login";
}
@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);
return "index";
} catch (UnknownAccountException e) {
model.addAttribute("msg", "用户名错误");
return "login";
} catch (IncorrectCredentialsException e) {
model.addAttribute("msg", "密码错误");
return "login";
}
}
5.shiro整合thymeleaf,前端页面的写法
-
导入命名空间
xmlns:shiro=“http://www.thymeleaf.org/thymeleaf-extras-shiro”
-
在div中添加 shiro:hasPermission=“user:add” 判断用户是否有add权限
具体代码如下
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.thymeleaf.org/thymeleaf-extras-shiro">
<head>
<head>
<meta charset="UTF-8">
<title>shiro</title>
</head>
<body>
<h1>首页</h1>
<p th:text="${msg}"></p>
<p>
<a th:href="@{/toLogin}">登陆</a>
</p>
<div shiro:hasPermission="user:add">
<a th:href="@{/user/add}">add</a>
</div>
<div shiro:hasPermission="user:update">
<a th:href="@{/user/update}">update</a>
</div>
</body>
</html>