Spring Security 安全框架搭建

Spring Security

安全简介

在Web开发中,安全第一位!!!安全虽属于应用的非功能性需求,但应当在应用开发系统设计之初就考虑进来,若开发后期才考虑安全的问题:

  • ​ 应用会存在严重的安全漏洞,可能造成用户隐私泄露
  • ​ 应用的基本架构已经确定,再考虑应用安全,修复安全漏洞,需要较大幅度调整系统架构,耗时耗力
  • ​ 认证,授权(admin,user1,user2,VIP)
    • ​ 功能权限
    • ​ 访问权限
    • ​ 菜单权限
    • ​ …
    • ​ 以前用拦截器、过滤器,
    • 产生大量的原生代码~

Web 应用的安全性包括 :

  • ​ Authentication:用户认证,验证某个用户是否为系统中的合法主体,即该用户能否访问该系统。常用的用户认证方式是系统通过检验用户名和密码来完成认证过程。
  • ​ Authorization: 用户授权,验证某个用户是否有权限执行某个操作,一个系统中不同用户具有的操作权限是不同的,比如说,有的用户只有查看权限,有的用户可编辑权限,一般,系统会为不同的用户分配不同的角色,而每个角色对应不同的操作权限。

java 众所周知的安全权限管理框架:ShiroSpring Security

认识Spring Security

Spring Security是一个java 安全框架,一个功能强大且高度可定制的身份验证和访问控制框架,是针对 spring 项目的安全框架,也是 spring boot 底层安全模块默认的技术选型,可实现强大的 web 安全控制。

Spring Security 框架支持的主流的认证方式:HTTP基本认证、HTTP表单验证、HTTP摘要认证、OpenID和LDAP等。

Spring Security框架在用户授权方面,提供基于角色的访问控制和访问控制列表(Access Control List, ACL),可以对应用中的领域对象进行细粒度的控制。

实战测试

环境搭建

1、新建一个初始的 spring boot 2.6.5 项目 web 模块,整合 thymeleaf 模块

	    <!-- 导入 thymeleaf模块-->
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-thymeleaf -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-thymeleaf</artifactId>
            <version>2.6.5</version>
        </dependency>

2、导入静态资源(需要的一些简单的前端测试页面) or 手写几个测试页面

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-TjpaG6jh-1648471124300)(C:\Users\86159\AppData\Roaming\Typora\typora-user-images\image-20220328202331117.png)]

3、controller 跳转!

@Controller
public class RouterController {

    @RequestMapping({"/","/index"})
    public String index(){
        return "index";
    }

    @RequestMapping("/toLogin")
    public String toLogin(){
        return "views/login";
    }

    @RequestMapping("/level1/{id}")
    public String level1(@PathVariable("id") int id){
        return "views/level1/" + id;
    }

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

    @RequestMapping("/level3/{id}")
    public String level3(@PathVariable("id") int id){
        return "views/level3/" + id;
    }
}

4、测试实验环境是否OK!

用户认证和授权

环境搭建好之后,对于spring boot项目的安全控制,只需要引入 spring-boot-starter-security 模块,进行少量的配置,即可实现强大的安全管理!!

记住几个类:

  • ​ WebSecurityConfigurerAdapter 自定义 Security 类
  • ​ AuthenticationManagerBuilder 自定义认证类
  • ​ @EnableWebSecurity 开启 WebSecurity 模式

Spring Security 的两个主要目标是"认证"和"授权"(访问控制),这两个概念是通用的,不只是在 Spring Security 中存在

目前,我们的测试环境,是所有人都可以访问,为了应用安全访问控制,使用 Spring Security

1、引入 Spring Security 模块

    <!--导入 Spring Security模块-->
        <!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
            <version>2.6.5</version>
        </dependency>

2、参考官网,编写 Spring Security 配置类 ,编写基础配置类 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("/level2/**").hasRole("vip3");

    }
}

到这一步,测试一下,除了首页,其它页面都无法进入,因为只有登录之后才有权限访问其他页面,目前还未配置登录的角色!

3、在configure(HttpSecurity http)方法中加入以下配置,开启自动配置的登录功能!

        //没有权限默认会到登录页面  此时我没有自己配置登录页,该登录页面是框架内置的
        http.formLogin();

到这一步,测试发现,没有权限时,会跳转到登录的页面!(该登录页面是 Spring Security 框架自带的)

4、查看刚才登录页的注释信息,我们可以定义认证规则,重写configure(AuthenticationManagerBuilder auth)方法

//AOP:
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //这些数据正常应该是从数据库中去取,这里用的是虚拟数据
        auth.inMemoryAuthentication()
                .withUser("xzh").password("123456").roles("vip2","vip3")
                .and()
                .withUser("root").password("123456").roles("vip1","vip2","vip3")
                .and()
                .withUser("guest").password("123456").roles("vip1");
    }
}

5、测试,使用这些账号登录进行测试,但是会报错!

  // 报错 java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

​ 原因,我们需要将前端传过来的密码进行某种方式的加密,否则就无法登录,修改代码!

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    //认证, springboot 2.1.x 可直接使用  这里springboot 2.6.5
    // 报错 java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"
    //报错原因: 在 Spring Security 5.0+ 新增了很多的加密方法
    // 要想我们的项目正常登录,需要修改一下configure中的代码,需将前端传过来的密码进行某种方式加密
    //spring security 官方推荐的是使用bcrypt加密方式
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        //这些数据正常应该是从数据库中去取,这里用的是虚拟数据
        auth.inMemoryAuthentication().passwordEncoder(new BCryptPasswordEncoder())
                .withUser("xzh").password(new BCryptPasswordEncoder().encode("123456")).roles("vip2","vip3")
                .and()
                .withUser("root").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1","vip2","vip3")
                .and()
                .withUser("guest").password(new BCryptPasswordEncoder().encode("123456")).roles("vip1");
    }
}

6、测试,登录成功,并且每个角色只能访问自己认证下的规则,Surprised!

注销及权限控制

1、注销,在configure(HttpSecurity http)方法中加入以下配置,开启注销功能

        http.csrf().disable();//这里如果注销失败,要关闭csrf功能,springboot 2.6.5版本 需要此步骤!!!
        http.logout().logoutSuccessUrl("/");

2、登录注销页面权限控制,在首页 index.html 中对未登录,已登录首页页面显示数据的控制

  <!--登录注销-->
            <div class="right menu">
               <!--如果未登录-->
                <div sec:authorize="!isAuthenticated()">
                    <a class="item" th:href="@{/toLogin}">
                        <i class="address card icon"></i> 登录
                    </a>
                </div>
                <!--如果已登录-->
                <div sec:authorize="isAuthenticated()">
                    <a class="item">
                        <i class="address card icon"></i>
                        用户名:<span sec:authentication="principal.username"></span>&nbsp;&nbsp;
                        角色:<span sec:authentication="principal.authorities"></span>
                    </a>
                </div>
                <div sec:authorize="isAuthenticated()">
                    <a class="item" th:href="@{/logout}">
                        <i class="address card icon"></i> 注销
                    </a>
                </div>

            </div>

记住我及首页定制

1、记住我,在configure(HttpSecurity http)方法中加入以下配置,开启记住我功能

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

2、首页定制,之前的登录页是框架自带的,这里在configure(HttpSecurity http)方法中加入以下配置,显示自定义登录页面

 //定制登录页 loginPage("/toLogin")
 // 这里底层框架默认 usernameParameter 为 username 所以可通过usernameParameter("user") 这样的方式自定义前端传来的参数 user,password同理
        http.formLogin().loginPage("/toLogin").usernameParameter("user").passwordParameter("pwd").loginProcessingUrl("/login");

完结!!!撒花!!!★,°:.☆( ̄▽ ̄)/$:.°★

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

xzh_2022

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值