《SpringBoot与Shiro整合-权限管理实战》
---- 从构建到模拟数据库登入
---- 点击下载源码
---- 或者查看?
文章目录
课程大纲
- 课程内容简介
- SpringBoot 与 Shiro框架简介
- SpringBoot 快速入门
- SpringBoot 与 Shiro 整合实现用户认证
- SpringBoot 与 Shiro 整合实现用户授权
- thymeleaf 和 shiro 标签整合使用
1. 课程内容简介
1.1. 内容简介
本课程主要讲解如何使用Spring Boot与Shiro进行整合使用,实现强大的用户权限管理,其中涉及如何完成用户认证(即用户登录) ,用户授权, thymeleaf页而整合shiro权限标签等知识点 。
1.2. 课程目标
快速掌握SpringBoot与Shiro安全框架的整合使用
1.3. 课程相关软件
idea
Spring Boot 2.2.1.RELEASE
Shiro 1.4.2 RELEASE
2. SpringBoot与Shiro框架简介
Spring的诞牛是lava企业版(Java Enterprise Edition, JEE,也称12EE)的轻量级代替品。无需开发重量级的Enterprise lavaBean (EIB) , Spring为企业级 Java开发提供了一种相对简单的方法,通过依赖注入和面向切面编程,用简单的Java对象(Plain Old Java Object, POIO)实现了EJB的功能。
虽然Spring的组件代码是轻量级的,但它的配置却是重量级的。
所有Spring配置都代表了开发时的损耗。因为在思考Spring特性配置和解决业务问题之间需要进行思维切换,所以写配置挤占了写应用程序逻辑的时间。除此之外,项目的依赖管理也是件吃力不讨好的事情,决定项目里要用哪些库就 已经够让人头痛的了,你还要知道这些库的哪个版本和其他库不会有冲突,这难·题实在太棘手,并且,依赖管理也是一种损耗,添加依赖不是写应用程序代码。一旦选错了依赖的版本,随之而来的不兼容问题毫无疑问会是生产力杀手。
Spring Boot让这一切成为了过去。
Spring Boot简化了基于Spring的应用开发,只需要"run"就能创建一个独立的、生产级别的Spring应用. Spring Boot为Spring 平台及第三方库提供开箱即用的设置(提供默认设置) ,这样我们就可以简单的开始。多数Spring Boot应用只需要很少的Spring配置。
我们可以使用SpringBoot创建java应用,并使用java-jar启动它,或者采用传统的war部署方式。
Spring Boot主要目标是:
- 为所有Spring的开发提供一个从根本上更快的入门体验。
- 并箱即用,但通过自己设置参数,即可快速摆脱这种方式。
- 提供了一些大型项目中常见的非功能性特性,如内嵌服务器、安全、指标,健康检测、外部化配置等。
- 绝对没有代码生成,也无需XML配置。
2.1 SpringBoot框架简介
Apache Shiro是一个强大且易用的ava安全框架,执行身份验证、授权、密码学和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序。
Apache Shiro体系结构
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-vBw5gsbh-1574444349194)(C:\Users\12696\Desktop\SpringFormWork\Shiro\image-20191123001942429.png)]
-
Authentication 认证 ---- 用户登录
-
Authorization 授权 ---- 用户具有哪些权限
-
Cryptography 安全数据加密
-
Session Management 会话管理
-
Web Integration web系统集成
-
Interations集成其它应用, spring、缓存框架
2. Spring Boot快速入门
2.1. @maven
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
2.2. @SpringBootApplication
@SpringBootApplicationpublic
class SpringBootShiroApplication {
public static void main(String[] args) { SpringApplication.run(SpringBootShiroApplication.class, args); }}
2.3. @Controller
/**
* 测试方法
*/
@RequestMapping("/hello")
@ResponseBodypublic String hello() {
System.out.println("UserController.hello()");
return "ok";}
3.5 导入 thymeleaf 页面模块
3.5.1. 引入 thymeleaf 依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
3.5.2. @Controller
/**
* 测试thymeleaf
*/
@RequestMapping("/testThymeleaf")
public String testThymeleaf(Model model) {
//把数据存入model
model.addAttribute("name", "黑马程序员");
//返回test.html
return "test";
}
3.5.3. @html
路径:\resources\templates\test.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>测试Thymeleaf的使用</title>
</head>
<body>
<h1>Test</h1>
<h3 th:text="${name}"></h3>
</hr>
进入用户添加功能:<a href="add">用户添加</a><br>
进入用户更新功能:<a href="update">用户更新</a>
</body>
</html>
4. Spring Boot与Shiro整合实现用户认证
4.1.分析Shiro的核心API
- Subject: 用户主体(把操作交给SecurityManager)
- SecurityManager:安全管理器(关联Realm)
- Realm: Shiro连接数据的桥梁
4.2. Spring Boot整合Shiro
4.2.1,导入 shiro 与spring 整合依赖
4.2.1 @maven
<!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring-boot-starter -->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring-boot-starter</artifactId>
<version>1.4.2</version></dependency>
4.2.2.自定义Realm类
public class UserRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("执行授权逻辑");
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行验证逻辑");
}
}
4.2.2,编写Shiro配置类 (*)
@Configuration
public class ShiroConfig {
/**
* 创建ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
return shiroFilterFactoryBean;
}
/**
* 创建DefaultWebSecurityManager
*/
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager( @Qualifier("userRealm")UserRealm userRealm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(userRealm);
return defaultWebSecurityManager;
}
/**
* 创建Realm
*/
@Bean(name = "userRealm")
public UserRealm getRealm(){
return new UserRealm();
}
}
4.3. 使用Shiro内置过滤器实现页面拦截
4.3.1 htmlCode
- 路径:\resources\templates\user\add.html
- 路径 \resources\templates\user\update.html
- 路径:\resources\templates\test.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>update</title>
</head>
<body>
<h1>update</h1>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>add</title>
</head>
<body>
<h1>add</h1>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>update</title>
</head>
<body>
<h1>update</h1>
</body>
</html>
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>测试Thymeleaf的使用</title>
</head>
<body>
<h1>Test</h1>
<h3 th:text="${name}"></h3>
</hr>进入用户添加功能:<a href="add">用户添加</a><br>
进入用户更新功能:<a href="update">用户更新</a>
</body>
</html>
/**
* 登入
* @return
*/
@RequestMapping("toLogin")
public String toLogin() {
return "/login";
}
/**
* 添加用户
* @return
*/
@RequestMapping("add")
public String add(){
return "user/add";
}
/**
* 更新用户
* @return
*/
@RequestMapping("update")
public String update() {
return "user/update";
}
@Configuration
public class ShiroConfig {
/**
* 创建ShiroFilterFactoryBean
*/
@Bean
public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//设置安全管理器
shiroFilterFactoryBean.setSecurityManager(securityManager);
//添加Shiro内置过滤器
/**
* Shiro内置过滤器,可以实现权限相关的拦截器
* 常用的过滤器:
* anon: 无需认证(登录) 可以访问
* authc: 必须认证才能可以访问
* user:如果使用rememMe的功能可以直接访问
* perms:该资源必须得到资源权限才可以访问
* role: 该资源必须得到角色权限才可以访问
*/
Map<String,String> filterMap = new LinkedHashMap();
// filterMap.put("/add","authc");
// filterMap.put("/update","authc");
filterMap.put("/testThymeleaf","anon");
filterMap.put("/*","authc");
//修改调整的登入界面
shiroFilterFactoryBean.setLoginUrl("/toLogin");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
return shiroFilterFactoryBean;
}
/**
* 创建DefaultWebSecurityManager
*/
@Bean(name="securityManager")
public DefaultWebSecurityManager getDefaultWebSecurityManager( @Qualifier("userRealm")UserRealm userRealm){
DefaultWebSecurityManager defaultWebSecurityManager = new DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(userRealm);
return defaultWebSecurityManager;
}
/**
* 创建Realm
*/
@Bean(name = "userRealm")
public UserRealm getRealm(){
return new UserRealm();
}
}
.4.4. 实现用户认证(登录)操作
路径:\resources\templates\login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.w3.org/1999/xhtml">
<head>
<meta charset="UTF-8">
<title>登入</title>
</head>
<body>
<h1>登入</h1>
<h3 th:text="${msg}" style="color:red"></h3>
<form method="post" action="login">
用户名:<input type="text" name="name"/><br/>
密码:<input type="text" name="password"><br/>
<input type="submit" value="登入"/>
</form>
</body>
</html>
. 4.4.2. 编写Controller的登录逻辑
/**
* 登录逻辑处理
*
* @return
*/
@RequestMapping("/login")
public String login(String name, String password, Model model) {
//打印数据
System.out.println("name="+name+"password="+password);
/**
* 使用Shiro编写认证操作
*/
//1.获取Subject
Subject subject = SecurityUtils.getSubject();
//2.封装用户数据
UsernamePasswordToken token = new UsernamePasswordToken(name, password);
//3.执行登录方法
try {
subject.login(token);
return "redirect:/testThymeleaf";
//登陆成功
} catch (UnknownAccountException e) {
//e.printStackTrace();
//登入失败:用户名不存在
model.addAttribute("msg", "用户名不存在");
return "login";
} catch (IncorrectCredentialsException e) {
//密码错误
model.addAttribute("msg", "密码错误");
return "login";
}
}
UserRealm
public class UserRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
System.out.println("执行授权逻辑");
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("执行验证逻辑");
//假设数据库的用户名和密码
String name = "eric";
String password = "123456";
//编写shiro判断逻辑,判断用户名和密码
//1.判断用户名
UsernamePasswordToken token1 = (UsernamePasswordToken)token;
System.out.println("token1:"+"name="+token1.getUsername()+"|||"+"password="+token1.getPassword());
if (!token1.getUsername().equals(name)) {
//用户名不存在
return null;//shiro底层会抛出异常UnKnowAccountException
}
//2.判断密码
//第一个参数是返回给登录的参数,第二个数据库密码,第三个shiro的名字
return new SimpleAuthenticationInfo("",password,"");
}
}
//1.判断用户名
UsernamePasswordToken token1 = (UsernamePasswordToken)token;
System.out.println("token1:"+"name="+token1.getUsername()+"|||"+"password="+token1.getPassword());
if (!token1.getUsername().equals(name)) {
//用户名不存在
return null;//shiro底层会抛出异常UnKnowAccountException
}
//2.判断密码
//第一个参数是返回给登录的参数,第二个数据库密码,第三个shiro的名字
return new SimpleAuthenticationInfo("",password,"");
}
}