7、SpringBoot:Spring Security

7.1、安全简介

在Web开发中,安全一直是非常重要的一个方面。安全虽然属于应用的非功能性需求,但是应该在应用开发的初期就考虑进来。如果在应用开发的后期才考虑安全的问题,就可能陷入一个两难的境地:一方面:应用的基本框架已经确定,无法满足用户的要求,并可能造成用户的隐私数据被攻击者窃取;另一方面,应用的基本框架已经确定,要修复安全漏洞,可能需要对系统的架构做出比较重大的调整,因而需要更多的开发时间,影响应用的发布进程。因此,从应用开发的第一天就应该把安全相关的因素考虑进来,并在整个应用的开发过程中。

市面上存在的比较有名的: Shiro, Spring Security

这里需要阐述以下的是,每一个框架的出现都是为了解决某一问题而产生的,那么Spring Security框架的出现是为了解决什么问题呢?

首先我们看下它的官网: 官网网址

Spring Security is a powerful and highly customizable authentication and access-control framework. It is the de-facto standard for securing Spring-based applications.

Spring Security is a framework that focuses on providing both authentication and authorization to Java applications. Like all Spring projects, the real power of Spring Security is found in how easily it can be extended to meet custom requirements

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

Spring Security是一个框架,侧重于为Java应用程序提供身份验证和授权。与所有Spring项目一样,Spring安全性的真正强大之处在于它可以轻松地扩展以满足定制需求

从官网的介绍中可以知道这是一个权限框架。想我们之前做项目是没有使用框架是怎么控制权限的?对于权限 一般会细分为功能权限,访问权限,和菜单权限。代码会写的非常的繁琐,冗余。

怎么解决之前写权限代码繁琐,冗余的问题,一些主流框架就应运而生而Spring Scecurity就是其中的一种。

Spring 是一个非常流行和成功的 Java 应用开发框架。Spring Security 基于 Spring 框架,提供了一套 Web 应用安全性的完整解决方案。一般来说,Web 应用的安全性包括用户认证(Authentication)和用户授权(Authorization)两个部分。用户认证指的是验证某个用户是否为系统中的合法主体,也就是说用户能否访问该系统。用户认证一般要求用户提供用户名和密码。系统通过校验用户名和密码来完成认证过程。用户授权指的是验证某个用户是否有权限执行某个操作。在一个系统中,不同用户所具有的权限是不同的。比如对一个文件来说,有的用户只能进行读取,而有的用户可以进行修改。一般来说,系统会为不同的用户分配不同的角色,而每个角色则对应一系列的权限。

对于上面提到的两种应用情景,Spring Security 框架都有很好的支持。在用户认证方面,Spring Security 框架支持主流的认证方式,包括 HTTP 基本认证、HTTP 表单验证、HTTP 摘要认证、OpenID 和 LDAP 等。在用户授权方面,Spring Security 提供了基于角色的访问控制和访问控制列表(Access Control List,ACL),可以对应用中的领域对象进行细粒度的控制。

7.2、Spring Security环境搭建

新建一个springboot项目

  1. 导入thymeleafjar包
        <!-- spring-boot-starter-thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>2.3.4.RELEASE</version>
        </dependency>
  1. 关闭thymeleaf的缓存
	# 关闭thymeleaf缓存
	spring.thymeleaf.cache=false
  1. 编写跳转各个页面的controller
@Controller
public class RouterController {

    // 跳转到首页
    @RequestMapping({"/","/index"})
    public String toIndex(){
        return "index";
    }
    // 跳转到登录页
    @RequestMapping("/toLogin")
    public String toLogin(){
        return "views/login";
    }
    // 跳转到level1
    @RequestMapping("/level1/{id}")
    public String toLevel1(@PathVariable("id") int id){
        return "views/level1/" +id;
    }

    // 跳转到level2
    @RequestMapping("/level2/{id}")
    public String toLevel2(@PathVariable("id") int id){
        return "views/level2/" +id;
    }

    // 跳转到level3
    @RequestMapping("/level3/{id}")
    public String toLevel3(@PathVariable("id") int id){
        return "views/level3/" +id;
    }
}
  1. 启动测试

在这里插入图片描述

7.3、Spring Security

注意

使用Aop理念,将配置类横切到项目中,不需要修改原代码

简介:

Spring Security 是针对于Spring项目的安全框架,也是Spring Boot底层安全模块默认的技术选型,他可以实现强大的Web安全控制,对于安全控制,我们仅需要引入spring-boot-starter-security模块,进行少量的配置,即可实现强大的安全管理

  • WebSecurityConfigurerAdapter:自定义Security策略
  • AuthenticationManagerBuilder:自定义认证策略
  • @EnableWebSecurity:开启WebSecurity模式

Spring Security的两个主要目标是“认证”和“授权”(访问控制)

  • “认证” (Authentication)
  • “授权” (Authentication)

这个概念是通用的,而不只是在Spring Security中存在

7.3.1、 导入Spring Security依赖

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

7.3.2、新建config目录,后在新建SecurityConfig 类

2.1、SecurityConfig模板

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        super.configure(http);
    }
}

2.2、编写SecurityConfig,进行权限划分

@EnableWebSecurity
public 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");
    }
}

2.3、启动项目进行测试

首页都可查看
在这里插入图片描述

其它页需要权限才能访问

在这里插入图片描述

所以我们将没有权限时的状态改为跳转到登录页面

只需要在SecurityConfig配置添加

		// 没有权限默认会到登录页面
        http.formLogin();

2.4、编写SecurityConfig,添加认证

    // 认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 从内存中获取 ==>  正常情况需要从数据库中获取
        auth.inMemoryAuthentication()
                .withUser("jl").password("111").roles("vip1","vip2")
                .and()
                .withUser("zs").password("222").roles("vip1","vip1","vip2");
    }

启动项目进行测试,登录会发现报错

在这里插入图片描述

所以这里我们需要对密码进行加密,那么如何加密呢?

在Spring Security 5.0 + 中新增了很多加密方法这里我们使用推荐的BCryptPasswordEncoder方法

具体使用

    // 认证
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 从内存中获取 ==>  正常情况需要从数据库中获取
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("jl").password(new BCryptPasswordEncoder().encode("111")).roles("vip1","vip2")
                .and()
                .withUser("zs").password(new BCryptPasswordEncoder().encode("222")).roles("vip1","vip1","vip2");
    }

加密之后,有权限就可以正常访问,没有权限的那么请登录

学习视频:学习网址

7.4、注销及权限控制

1、注销

在登录页面添加注销按钮

<!--登录注销-->
            <div class="right menu">
                <!--未登录-->
                <a class="item" th:href="@{/toLogin}">
                    <i class="address card icon"></i> 登录
                </a>
                <!--注销-->
                <a class="item" th:href="@{/logout}">
                    <i class="sign-out icon"></i> 注销
                </a>
            </div>

推荐图标网站https://semantic-ui.com/

效果:

在这里插入图片描述

注销功能只需要在SecurityConfig配置中添加以下业务,这里指的是注销session之后跳转到首页

		// 开启注销
        http.logout().logoutSuccessUrl("/");

2、权限控制

1、未登录,则显示登陆按钮,登录,则显示用户名和注销按钮

  1. 导入thymeleaf-security整合包
		<!-- thymeleaf-security整合包 -->
        <dependency>
            <groupId>org.thymeleaf.extras</groupId>
            <artifactId>thymeleaf-extras-springsecurity4</artifactId>
            <version>3.0.4.RELEASE</version>
        </dependency>
  1. 修改index.xml,在里边加入判断,如果未登录,则显示登陆按钮,如果已经登陆,那么显示用户名和注销按钮
			<!--登录注销-->
            <div class="right menu">
                <!-- 如果未登录,则显示登陆按钮-->
                <div sec:authorize="!isAuthenticated()">
                    <a class="item" th:href="@{/toLogin}">
                        <i class="address card icon"></i> 登录
                    </a>
                </div>

                <!--如果已登录,则显示用户名和注销按钮-->
                <div sec:authentication="isAuthenticated()">
                    <a class="item">
                        用户名:<span sec:authentication="name"></span>
                    </a>
                </div>
                <div sec:authentication="isAuthenticated()">
                    <a class="item" th:href="@{/logout}">
                        <i class="sign-out icon"></i> 注销
                    </a>
                </div>
            </div>
  1. 启动测试

注意这里springboot需要降级,将版本改为2.0.9.RELEASE,不降级的时候,它不支持Spring Security

在这里插入图片描述

降级之后再次启动项目查看,发现问题解决

在这里插入图片描述
注意,这里点击注销会报错

在这里插入图片描述
为什么会报错呢?

因为这里涉及到了网站攻击,这里登陆提交的方式是get,不安全,而springboot默认情况下是crsf是开启的,所以我们需要关闭(如果提交方式是post时,那么不用关闭)

        //关闭防止网站攻击
        http.csrf().disable();

关闭之后就可以正常注销了

2、根据角色控制菜单的显示

通过用户角色判断可以动态的实现模块的动态显示

在这里插入图片描述

启动进行测试

  1. 主页不会显示菜单,因为当前没有用户登录,所有没有角色

在这里插入图片描述

  1. 登录之后,根据自己的权限,显示自己的模块

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
https://www.bilibili.com/video/BV1PE411i7CV?p=36

学习视频:学习网址

7.5、记住我和首页定制

7.5.1、实现记住我功能

  • 第一步,开启记住我功能,本质就是将内容存入到cookie中
	// 开启记住我
    http.rememberMe();

7.5.1、首页定制

Spring Security默认的登录页面http.formLogin()

那么如何定制我们自己的页面呢?修改SecurityConfig

  • 第一种方式
		// 定制自己的登录页面
        http.formLogin().loginPage("/toLogin");

login页面跳转路径也需要修改

在这里插入图片描述

  • 第二种方式
		// 定制自己的登录页面   
    	http.formLogin().loginPage("/toLogin").loginProcessingUrl("/login");

login页面跳转路径也需要修改
在这里插入图片描述
注意

登录时默认接收的参数为username,password

在这里插入图片描述

如果前端页面的参数不是默认的username,password,那么需要在SecurityConfig中自定义参数

在这里插入图片描述

自定义方法

	// 定制自己的登录页面
    http.formLogin().loginPage("/toLogin").usernameParameter("user").passwordParameter("pwd").loginProcessingUrl("/login");

7.5.3、添加记住我

login登录页面

	<div class="field">
        <input type="checkbox" name="remember"> 记住我
    </div>

SecurityConfig配置

	// 开启记住我功能,  cookie  默认保存两周,自定义接收前端的参数
    http.rememberMe().rememberMeParameter("remember");

在这里插入图片描述

学习视频:学习网址

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值