shiro具体实现
1)登录拦截
shiro的核心过滤器:
-
controller:
-
ShiroConfig:
-
目录:
2)用户认证
- login.html:
<body>
<h1>登录页面</h1>
<hr>
<p th:text="${msg}" style="color: red"></p>
<form th:action="@{/login}">
<p>用户名: <input type="text" name="username"></p>
<p>密码: <input type="password" name="password"></p>
<p><input type="submit" ></p>
</form>
</body>
- cotroller:
@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";//登陆成功则转到index.html页面
} catch (UnknownAccountException e) { //用户不存在的异常
model.addAttribute("msg","用户名错误!");
return "login";
} catch (IncorrectCredentialsException e) { //密码错误异常
model.addAttribute("msg", "密码错误!");
return "login";
}
}
- UserRealm:
//自定义的realm
public class UserRealm extends AuthorizingRealm {
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权doGetAuthorizationInf");
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证doGetAuthorizationInf");
//用户名,密码 应该到数据库中取,这里为了方便,自己伪造一个
String name="root";
String password="123456";
UsernamePasswordToken userToken=(UsernamePasswordToken)authenticationToken;
//用户名认证:如果前端获取的用户名和设定的不一致则返回null
if (!userToken.getUsername().equals(name)){
return null;//return null会抛出UnknownAccountException异常
}
//密码认证,不用自己写,由shiro来完成
return new SimpleAuthenticationInfo("",password,"");
}
}
- 运行测试:
3)整合MyBatis
- 1.首先需要导入对应的依赖
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.28</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>druid-spring-boot-starter</artifactId>
<version>1.1.21</version>
</dependency>
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
- 2.连接mysql数据库
- 3.写一个yml
直接拷贝之前博客写好的yml内容:https://www.cnblogs.com/kakafa/p/15960412.html
spring:
datasource:
username: root
password: 123456
driver-class-name: com.mysql.cj.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatistest?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT
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
maxPoolPreparedStatementPerConnectionSize: 20
useGlobalDataSourceStat: true
connectionProperties: druid.stat.mergeSql=true;druid.stat.slowSqlMillis=500
- 4.配置mybatis,并且完成pojo和mapper的建立和编写
UserRealm:
//自定义的realm
public class UserRealm extends AuthorizingRealm {
@Autowired
UserService userService;
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权doGetAuthorizationInf");
return null;
}
//认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证doGetAuthorizationInf");
UsernamePasswordToken userToken=(UsernamePasswordToken)authenticationToken;
//连接真实数据库
User user = userService.queryByUsername(userToken.getUsername());
if (user==null){ //没有这个人
return null;
}
//密码认证,不用自己写,由shiro来完成
return new SimpleAuthenticationInfo("",user.getPwd(),"");
}
}
测试结果:
4)请求授权实现
ShiroConfig:
@Configuration
public class ShiroConfig {
//ShiroFilterFactoryBean
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("dwsm") DefaultWebSecurityManager sm){
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean();
//设置安全管理器
bean.setSecurityManager(sm);
//添加shiro的内置过滤器
Map<String,String> filterMap = new LinkedHashMap<>();
//授权 未授权的情况下会跳转到401错误页面,即提示未授权页面;也可以自定义未授权提示:bean.setUnauthorizedUrl("/unauth");
filterMap.put("/user/add","perms[user:add]");//"perms[user:add]"必须是user这个用户并且偶对add的访问权限
filterMap.put("/user/*","authc");//需要认证了才能访问user目录下的页面
bean.setFilterChainDefinitionMap(filterMap);
bean.setLoginUrl("/toLogin");//如果没有权限,则跳转到登录页面,这里是设置登录页面的请求地址
//未授权页面
bean.setUnauthorizedUrl("/unauth");
return bean;
}
//DefaultWebSecurityManager
@Bean(name = "dwsm")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联UserRealm
securityManager.setRealm(userRealm);
return securityManager;
}
//创建 realm 对象 需要自定义一个类UserRealm
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
}
这一步是给用户授予权限:
UserRealm:
//授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权doGetAuthorizationInf");
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.addStringPermission("user:add");
return info;
}
重启测试后,发现所有能登录的用户都可以正常访问add页面了。但是实际情况应该书部分用户有授权而不是所有用户,因此这里做如下改动:
给user表增加一个perms字段:相对应的pojo实体类也得改
5)整合thymeleaf
- 1.先导入pom依赖
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.1.0</version>
</dependency>
- 2.ShiroConfig:
//整合shiroDialect:用来整合shiroThemeleaf
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
-
- index.html:使得首页的部分连接值对拥有相应授权的用户显示
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>首页</h1>
<p shiro:notAuthenticated>
<a th:href="@{/toLogin}">登录</a>
</p>
<p th:text="${msg}"></p>
<!--shiro:hasPermission="user:add"这里冒号会报错,加一层单引号即可-->
<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>
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律