1.SpringBoot整合Shiro思路
2. 环境搭建
2.1 创建项目
2.2 引入依赖
pom.xml
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--引入Jsp依赖-->
<dependency>
<groupId>org.apache.tomcat.embed</groupId>
<artifactId>tomcat-embed-jasper</artifactId>
</dependency>
<!--jstl-->
<dependency>
<groupId>jstl</groupId>
<artifactId>jstl</artifactId>
<version>1.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</exclude>
</excludes>
</configuration>
</plugin>
</plugins>
</build>
2.3 创建前端页面
在webapp文件夹中创建index.jsp和login.jsp
index.jsp
<%@page contentType="text/html;UTF-8" pageEncoding="UTF-8" isErrorPage="false" %>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<%--受限资源--%>
<h1>系统主页</h1>
<ul>
<li><a href="#">用户管理</a></li>
<li><a href="#">商品管理</a></li>
<li><a href="#">订单管理</a></li>
<li><a href="#">物流管理</a></li>
</ul>
</body>
</html>
login.jsp
<%@page contentType="text/html;UTF-8" pageEncoding="UTF-8" isErrorPage="false" %>
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<h1>登录界面</h1>
<form action="${pageContext.request.contextPath}/user/login" method="post">
用户名:<input type="text" name="username" > <br/>
密码 : <input type="text" name="password"> <br>
<input type="submit" value="登录">
</form>
</html>
2.4 配置视图信息
application.properties
server.port=8080
server.servlet.context-path=/shiro
spring.application.name=shiro
spring.mvc.view.prefix=/
spring.mvc.view.suffix=.jsp
2.5 解决IDEA冲突问题
JSP 与IDEA 与SpringBoot存在一定的不兼容,修改此配置即可解决
2.6 测试搭建的环境
3. 整合Shiro
3.1 引入依赖
pom.xml
<!--引入shrio-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.5.3</version>
</dependency>
3.2 自定义Realm
在shiro文件夹下创建realm文件夹
package com.test.shiro.realm;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
/**
* 自定义Realm
*/
public class CustomerRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
return null;
}
}
3.3 Shiro配置
在config文件夹中创建ShiroConfig.java
@Configuration
public class ShiroConfig {
//ShiroFilter过滤所有请求
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//给ShiroFilter配置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
//配置系统受限资源
//配置系统公共资源
Map<String, String> map = new HashMap<String, String>();
map.put("/index.jsp","authc");//表示这个资源需要认证和授权
// 设置认证界面路径
shiroFilterFactoryBean.setLoginUrl("/login.jsp");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//创建安全管理器
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm);
return securityManager;
}
//创建自定义Realm
@Bean
public Realm getRealm() {
CustomerRealm realm = new CustomerRealm();
return realm;
}
}
3.4 启动测试
输入http://localhost:8080/shiro/index.jsp,发现需要跳转到login.jsp
4. 常见过滤器
- 注意: shiro提供和多个默认的过滤器,我们可以用这些过滤器来配置控制指定url的权限:
5. 认证和退出
5.1 在index.jsp添加a标签
index.jsp
<a href="${pageContext.request.contextPath}/user/logout">退出登录</a>
5.2 编写controller
UserController.java
@Controller
@RequestMapping("/user")
public class UserController {
@RequestMapping("logout")
public String logout() {
Subject subject = SecurityUtils.getSubject();
subject.logout();
return "redirect:/login.jsp";
}
@RequestMapping("/login")
public String login(String username, String password) {
//获取主题对象
Subject subject = SecurityUtils.getSubject();
try {
subject.login(new UsernamePasswordToken(username,password));
System.out.println("登录成功!!!");
return "redirect:/index.jsp";
} catch (UnknownAccountException e) {
e.printStackTrace();
System.out.println("用户错误!!!");
} catch (IncorrectCredentialsException e) {
System.out.println("密码错误!!!");
}
return "redirect:/login.jsp";
}
}
5.3 修改自定义Realm
CustomerRealm.java
/**
* 自定义Realm
*/
public class CustomerRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
String principal = (String) authenticationToken.getPrincipal();
if ("zhangsan".equals(principal)) {
return new SimpleAuthenticationInfo(principal,"123456",this.getName());
}
return null;
}
}
5.4 修改ShiroConfig配置
ShiroConfig.java
公共资源一定是在受限资源上面,不然会造成死循环。
@Configuration
public class ShiroConfig {
//ShiroFilter过滤所有请求
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(DefaultWebSecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//给ShiroFilter配置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
//配置系统受限资源
//配置系统公共资源
Map<String, String> map = new HashMap<String, String>();
map.put("/user/login","anon");//表示这个为公共资源 一定是在受限资源上面
map.put("/**","authc");//表示这个受限资源需要认证和授权
// 设置认证界面路径
shiroFilterFactoryBean.setLoginUrl("/login.jsp");
shiroFilterFactoryBean.setFilterChainDefinitionMap(map);
return shiroFilterFactoryBean;
}
//创建安全管理器
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(Realm realm) {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(realm);
return securityManager;
}
//创建自定义Realm
@Bean
public Realm getRealm() {
CustomerRealm realm = new CustomerRealm();
return realm;
}
}
5.5 测试
登录正常,登出正常,未登录和登出后不能访问index.jsp
6. MD5、Salt的认证实现
6.1 创建数据库
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for t_user
-- ----------------------------
DROP TABLE IF EXISTS `t_user`;
CREATE TABLE `t_user` (
`id` INT(6) NOT NULL AUTO_INCREMENT,
`username` VARCHAR(40) DEFAULT NULL,
`password` VARCHAR(40) DEFAULT NULL,
`salt` VARCHAR(255) DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=INNODB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
SET FOREIGN_KEY_CHECKS = 1;
6.2 引入依赖
<!--引入mybatis-->
<dependency>
&l