[SpringBoot+Shiro] 简单实现验证+授权案例
目录
- Spring Boot
- Shiro
- Thymeleaf
- Mybatis Plus (也可以自己选择使用其他访问数据库数据的方法)
- ShiroConfig.java
@Configuration
public class ShiroConfig {
//ShiroFilterFactoryBean 第三步 注入第二步的DefaultWebSecurityManager
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(defaultWebSecurityManager);
//添加shiro内置过滤器
/*
* anon:无须认证就可以访问
* authc:必须认证了才能访问
* user:必须拥有 记住我 功能才能用
* perms:拥有对某个资源的权限才能访问
* role:拥有某个角色权限才能访问
* */
//拦截
Map<String,String> filterMap = new LinkedHashMap<>();
filterMap.put("/user/add","perms[user:add]"); //要有user:add的权限才能访问/user/add页面,从数据库中获取校验
filterMap.put("/user/update","perms[user:update]"); //要有user:update的权限才能访问/user/update页面,从数据库中获取校验
filterMap.put("/user/*","authc"); //所有user下的请求都需要经过用户认证才阔以访问
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap); //设置过滤拦截map
shiroFilterFactoryBean.setLoginUrl("/toLogin"); //设置登录请求的页面
shiroFilterFactoryBean.setUnauthorizedUrl("/noauth"); //设置未经授权跳转的页面
return shiroFilterFactoryBean;
}
//DefaultWebSecurityManager 第二步 注入第一步的real
@Bean(name = "securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
//关联Realm
securityManager.setRealm(userRealm);
return securityManager;
}
//创建real对象,需要自定义 第一步
@Bean
public UserRealm userRealm(){
return new UserRealm();
}
}
- UserRealm.java
//自定义的UserRealm
public class UserRealm extends AuthorizingRealm {
//自动注入Service
@Autowired
UserService userService;
//访问授权
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行了授权=》doGetAuthorizationInfo");
//SimpleAuthorizationInfo
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
//拿到当前登录的对象,从下面认证中拿,new SimpleAuthenticationInfo(user,user.getPassword(),""); 中的第一个参数user
Subject subject = SecurityUtils.getSubject();
//拿到经过了认证的当前对象User
User currentUser = (User) subject.getPrincipal();
//为当前用户添加的权限,从数据库中获取的字段权限
info.addStringPermission(currentUser.getPerms());
return info;
}
//登录认证
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行了认证=》doGetAuthorizationInfo");
//获取经过controller登录封装的token
UsernamePasswordToken userToken = (UsernamePasswordToken) authenticationToken;
String username = userToken.getUsername();
//从数据库中查找登录用户的信息 这里我使用了MyBatis Plus的方法
User user = userService.getOne(new QueryWrapper<User>().eq("username", username), false);
System.out.println("user:" + user);
//用户名验证
if (!userToken.getUsername().equals(user.getUsername())) {
//抛出异常 UnknownAccountException 用户名不存在
return null;
}
//密码验证 shiro会自己去做,这里的第一个参数,传进来,之后通过SecurityUtils.getSubject(); subject.getPrincipal(); 就可以获得这个user对象
return new SimpleAuthenticationInfo(user, user.getPassword(), "");
}
}
- ShiroConroller.java
@Controller
public class ShiroController {
//返回主页
@RequestMapping({"/","index"})
public String toIndex(Model model){
model.addAttribute("msg","hello,Shiro");
return "index";
}
//返回添加页面
@RequestMapping("/user/add")
public String add(){
return "user/add";
}
//返回更新页面
@RequestMapping("/user/update")
public String update(){
return "user/update";
}
//返回登录页面
@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";
}
}
//没有经过授权的页面
@RequestMapping("/noauth")
@ResponseBody
public String Unauthorized(){
return "未经授权,不能访问该页面";
}
}
- pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.example</groupId>
<artifactId>shiro-springboot</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>shiro-springboot</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<!-- 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-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<!--mp-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-freemarker</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--mp代码生成器-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-generator</artifactId>
<version>3.2.0</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.12</version>
</dependency>
<dependency>
<groupId>org.apache.velocity</groupId>
<artifactId>velocity-tools</artifactId>
<version>2.0</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
- index.html
<!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>
- login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<h1>login</h1>
<p th:text="${msg}" style="color: red"></p>
<form th:action="@{/login}">
<p>用户名:<input type="text" name="username"></p>
<p>密码:<input type="text" name="password"></p>
<p><input type="submit"></p>
</form>
</body>
</html>
页面展示
主页
登录页
add页(需经过认证和授权)
update页(需经过认证和授权)
未经授权页
数据库
!