> 文档中心 > SpringBoot学习---SpringSecurity与Shiro

SpringBoot学习---SpringSecurity与Shiro

视频学习链接:
在这里插入图片描述
狂神说SpringBoot18:集成SpringSecurity

目录:

      • 一.SpringSecurity
        • 1.什么是SpringSecurity
        • 2.实际操作
          • (1) 项目框架
          • (2) 项目使用的依赖(在pom.xml中)
          • (3) 前端界面
          • (4) controller层实现页面的跳转
          • (5) SpringSecurity的使用
          • (6) 运行效果
      • 二.Apache Shiro
        • 1.什么是Apache Shiro
        • 2.三大核心组件
        • 3.四大核心功能
        • 4.实际操作
          • (1) 项目结构
          • (2) 导入依赖(在pom.xml中)
          • (3) 前端界面
          • (4) controller层实现页面的跳转
          • (5) Dao层用户的数据从数据库中获取
          • (6) Service层
          • (7) Shiro的使用
          • (8) 运行效果

一.SpringSecurity

1.什么是SpringSecurity

Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。它实际上是保护基于spring的应用程序的标准。

2.实际操作

需求:根据用户的权限,限制用户可进入的页面,如用户权限为VIP1可以访问/level1/下的所有页面,用户权限为VIP2可以访问/level2/下的所有页面,用户权限为VIP3可以访问/level3/下的所有页面。
在这里插入图片描述

(1) 项目框架

在这里插入图片描述

(2) 项目使用的依赖(在pom.xml中)
  <dependency>     <groupId>org.thymeleaf</groupId>     <artifactId>thymeleaf-spring5</artifactId> </dependency>  <dependency>     <groupId>org.springframework.boot</groupId>     <artifactId>spring-boot-starter-security</artifactId> </dependency>  <dependency>     <groupId>org.thymeleaf.extras</groupId>     <artifactId>thymeleaf-extras-springsecurity5</artifactId> </dependency>
(3) 前端界面

在这里插入图片描述
Login.html:用户登入页面

<!DOCTYPE html><html lang="en" xmlns="http://www.w3.org/1999/html"><head>    <meta charset="UTF-8">    <title>Title</title></head><body><form action="/index" method="post">    <p>账号:</p><input type="text" placeholder="请输入账号" name="userName">    <p>注销:</p><input type="password" placeholder="请输入密码" name="passWord">    </br>    <input type="checkbox" name="remember">记住我    </br>    <input type="submit" value="登入"></form></body></html>

index.html:网站主界面

<!DOCTYPE html><html lang="en" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"><head>    <meta charset="UTF-8">    <title>Title</title></head><body><H1>首页</H1><div class="right menu">        <div sec:authorize="!isAuthenticated()"> <a th:href="@{/tologin}" class="item"/>登入    </div>    <div sec:authorize="isAuthenticated()"> <a class="item">     用户名: <span sec:authentication="name"></span>     角色:<span sec:authentication="principal.authorities"></span> </a>    </div>    <div sec:authorize="isAuthenticated()"> <a th:href="@{/logout}"  class="item"/>注销    </div></div><div sec:authorize="hasRole('VIP1')">    <h2>level1</h2>    <a href="/level1/1">level1-1</a>    <a href="/level1/2">level1-2</a>    <a href="/level1/3">level1-3</a></div><div sec:authorize="hasRole('VIP2')">    <h2>level2</h2>    <a href="/level2/1">level2-1</a>    <a href="/level2/2">level2-2</a>    <a href="/level2/3">level2-3</a></div><div sec:authorize="hasRole('VIP3')">    <h2>level3</h2>    <a href="/level3/1">level3-1</a>    <a href="/level3/2">level3-2</a>    <a href="/level3/3">level3-3</a></div></body></html>

/leve1/X.html随便写写即可
在这里插入图片描述

(4) controller层实现页面的跳转

SecurityProjectController类:
在这里插入图片描述

(5) SpringSecurity的使用

经过前面操作,基本上可以实现界面的跳转,但是还无法实现根据用户权限的不同,展示不同的页面,这个时候我们需要使用SpringSecurity。

  • 导入SpringSecurity的依赖
    在这里插入图片描述
  • 在config中创建SecurityConfig类(自定义Spring Security 配置类)
@EnableWebSecuritypublic class SecurityConfig extends WebSecurityConfigurerAdapter {    // 授权    @Override    protected void configure(HttpSecurity http) throws Exception { // 定制请求的授权规则 http.authorizeRequests()  .antMatchers("/").permitAll()  .antMatchers("/level1/").hasRole("VIP1")  .antMatchers("/level2/").hasRole("VIP2")  .antMatchers("/level3/").hasRole("VIP3"); // 开启登入 http.formLogin().loginPage("/tologin").usernameParameter("userName").passwordParameter("passWord").loginProcessingUrl("/index");// 注销 http.logout().logoutSuccessUrl("/tologin"); http.csrf().disable(); // 开启记住我功能 http.rememberMe().rememberMeParameter("remember");    }    // 认证    @Override    protected void configure(AuthenticationManagerBuilder auth) throws Exception {// 从内存中定义 auth.inMemoryAuthentication()  .passwordEncoder(new BCryptPasswordEncoder())  .withUser("admin").password(new BCryptPasswordEncoder().encode("123456")).roles("VIP1")  .and()  .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("VIP2")  .and()  .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("VIP3");    }}

WebSecurityConfigurerAdapter:自定义Security策略(自定义Spring Security 配置类继承该类即可)
SpringBoot学习---SpringSecurity与Shiro

@EnableWebSecurity:开启WebSecurity模式
在这里插入图片描述

AuthenticationManagerBuilder:自定义认证策略
在这里插入图片描述
Spring Security的两个主要目标是 “认证” 和 “授权”(访问控制):
重写configure(HttpSecurity http)方法用于授权
在这里插入图片描述
重写configure(AuthenticationManagerBuilder auth)方法用于认证
在这里插入图片描述

(6) 运行效果

在这里插入图片描述
这个登入界面是使用自己编写的(SpringSecurity本身提供登入界面)
SpringBoot学习---SpringSecurity与Shiro
登入admin(权限为VIP1)

在这里插入图片描述
在这里插入图片描述
登入root(权限为VIP2)
在这里插入图片描述
登入guest用户(权限为VIP3)
在这里插入图片描述

二.Apache Shiro

1.什么是Apache Shiro

Apache Shiro是一个功能强大且易于使用的Java安全框架,提供了认证,授权,加密,和会话管理。如同 Spring security 一样都是是一个权限安全框架,但是与Spring Security相比,在于他使用了和比较简洁易懂的认证和授权方式。

2.三大核心组件

  • subject:主体,可以是用户也可以是程序,主体要访问系统,系统需要对主体进行认证、授权。
  • securityManager: 安全管理器,主体进行认证和授权都是通过它进行。
  • realm:领域,可以理解为DAO,通过它存取认证、授权相关数据。

3.四大核心功能

  • Authentication:认证即登录,用于用户身份识别。
  • Authorization: 授权即访问控制,判断用户是否有权限去访问受保护的资源。
  • Cryptography: 通过加密算法保护数据安全。
  • Session Management:会话管理,即用户访问你应用自身携带的数据,甚至可以在非Web程序

4.实际操作

需求:通过查询用户的perms字段的值,如果为user:add表示该用户可以进入add.html;如果为user:update表示该用户进入update.html
在这里插入图片描述

(1) 项目结构

在这里插入图片描述

(2) 导入依赖(在pom.xml中)
 <!--导入shiro依赖--> <dependency>     <groupId>org.apache.shiro</groupId>     <artifactId>shiro-spring</artifactId>     <version>1.4.1</version> </dependency> <!--数据库--> <dependency>     <groupId>mysql</groupId>     <artifactId>mysql-connector-java</artifactId>     <version>8.0.19</version> </dependency> <dependency>     <groupId>log4j</groupId>     <artifactId>log4j</artifactId>     <version>1.2.17</version> </dependency> <dependency>     <groupId>com.alibaba</groupId>     <artifactId>druid</artifactId>     <version>1.1.12</version> </dependency> <dependency>     <groupId>org.mybatis.spring.boot</groupId>     <artifactId>mybatis-spring-boot-starter</artifactId>     <version>2.1.1</version> </dependency> <dependency>     <groupId>org.projectlombok</groupId>     <artifactId>lombok</artifactId> </dependency> <dependency>     <groupId>com.github.theborakompanioni</groupId>     <artifactId>thymeleaf-extras-shiro</artifactId>     <version>2.0.0</version> </dependency>
(3) 前端界面

在这里插入图片描述
index.html:网站首页界面

<!DOCTYPE html><html lang="en"      xmlns:th="https://www.thymeleaf.org"      xmlns:shiro="https://shiro.apache.org/jsp-tag-library.html"><head>  <meta charset="UTF-8">  <title>Title</title></head><body><h1>首页</h1><p th:text="${msg}" style="color: red;"></p><shiro:notAuthenticated>  <a th:href="@{/toLogin}">登入</a></shiro:notAuthenticated><shiro:authenticated>      <shiro:haspermission name="user:add">    <a th:href="@{/user/add}">add</a>  </shiro:haspermission>  <shiro:haspermission name="user:update">    <a th:href="@{/user/update}">update</a>  </shiro:haspermission></shiro:authenticated></body></html>

login.html:用户登入界面

<!DOCTYPE html><html lang="en"  xmlns:shiro="https://www.thymeleaf.org/thymeleaf-extras-shiro"><head>    <meta charset="UTF-8">    <title>登入界面</title></head><body><form th:action="@{/submitLogin}" method="post">    <p th:text="${msg}" style="color: red;"></p>   账号:<input type="text" name="userName">  密码:<input type="password" name="passWord">   <input type="submit" value="登入"></form></body></html>

User下的add.html和update.html随便写写即可:
在这里插入图片描述

(4) controller层实现页面的跳转
@Controllerpublic class MyController {    @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("/submitLogin")    public String login(@RequestParam("userName") String username, @RequestParam("passWord")String passWord, Model model){ // 获取当前对象 Subject subject = SecurityUtils.getSubject(); // 封装用户的登入数据 UsernamePasswordToken token =new UsernamePasswordToken(username,passWord); System.out.println("进行登入!"); try {     subject.login(token);// 执行登入方法     return "index"; }catch (UnknownAccountException e){     model.addAttribute("msg","用户名错误");     return "login"; }catch (IncorrectCredentialsException e){     model.addAttribute("msg","密码错误");     return "login"; }    }    @ResponseBody    @RequestMapping("/auth")    public String noauth(){ return  "没有授权!";    }}

这里注意登入使用的Subject对象进行登入:
在这里插入图片描述

(5) Dao层用户的数据从数据库中获取

数据表结构:
在这里插入图片描述
数据:
在这里插入图片描述
数据源配置application.yaml中:

spring:  datasource:    username: root    password: root    url: jdbc:mysql://localhost:3306/mybatis?useUnicode=true&characterEncoding=UTF-8&serverTimezone=UTC    driver-class-name: com.mysql.cj.jdbc.Driver

pojo:
在这里插入图片描述

Mapper层:
SpringBoot学习---SpringSecurity与Shiro
在这里插入图片描述
不要忘了扫描一下包:
application.properties中
SpringBoot学习---SpringSecurity与Shiro
由于映射文件UserMapper.xml放在Java文件中(资源过滤),不然无法生成该UserMapper.xml:

 <resource>  <directory>src/main/java</directory>  <includes>      <include>/*.xml</include>  </includes>     </resource>

在这里插入图片描述

(6) Service层

UserService接口:
在这里插入图片描述
UserServiceImpl实现类:
在这里插入图片描述

(7) Shiro的使用
  • ShiroConfig配置

三个bean对象:(userRealm,DefaultWebSecurityManager,ShiroFilterFactoryBean)

@Configurationpublic class ShiroConfig {    // ShiroFilterFactoryBean    @Bean    public ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager defaultWebSecurityManager) { ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); // 设置安全管理器 bean.setSecurityManager(defaultWebSecurityManager); // 添加shiro的内置过滤器 Map<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("/auth"); return bean;    }    // DefaultWebSecurityManager    @Bean(name = "securityManager")    public DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("userRealm") UserRealm userRealm) { // 关联UserRealm DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(userRealm); return securityManager;    }    // 创建realm对象    @Bean    public UserRealm userRealm() { return new UserRealm();    }    @Bean    public ShiroDialect shiroDialect(){ return new ShiroDialect();    }}
  • 授权与认证userService类
public class UserRealm extends AuthorizingRealm {    @Autowired    private UserServiceImpl userService;    // 授权    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("执行了=>授权doGetAuthorizationInfo");// 进行授权 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); // 通过数据库授权 Subject subject = SecurityUtils.getSubject(); User user = (User) subject.getPrincipal(); info.addStringPermission(user.getPerms()); return info;    }    // 认证    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("执行了=>验证doGetAuthenticationInfo");// // 获取用户名,密码 UsernamePasswordToken userToken = (UsernamePasswordToken) token; User user = userService.getUserByName(userToken.getUsername()); if (user == null){     return null; } // 密码验证 return new SimpleAuthenticationInfo(user,user.getPwd(),"");    }}
(8) 运行效果

在这里插入图片描述

登入admin用户(只有add权限):
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

登入测试(只有update权限):

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

神漫画