Springboot整合SpringSecurity入门

目录
  • SpringSecurity概述
  • 框架核心组件
    • 核心组件
    • 过滤器总结
  • SpringSecurity测试环境部署
    • 导入依赖
    • 创建静态页面
    • 创建控制器
  • Springboot整合SpringSecurity
    • 导入依赖
    • 创建SpringSecurity配置类
    • 设置用户访问权限不足的跳转页面
    • 注销功能
    • SpringSecurity 整合 Thymeleaf
    • 记住我功能
    • 自定义登录页面
  • SpringSecurity 整合 数据库

SpringSecurity概述

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

需要牢记的几个类:

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

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

“授权” (Authorization)

授权发生在系统成功验证您的身份后,最终会授予您访问资源(如信息,文件,数据库,资金,位置,几乎任何内容)的完全权限。

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

“认证”(Authentication)

身份验证是关于验证您的凭据,如用户名/用户ID和密码,以验证您的身份。

身份验证通常通过用户名和密码完成,有时与身份验证因素结合使用。

框架核心组件

核心组件

  • SecurityContextHolder:提供对SecurityContext的访问
  • SecurityContext:持有Authentication对象和其他可能需要的信息
  • AuthenticationManager: 其中可以包含多个AuthenticationProvider
  • ProviderManager:对象为AuthenticationManager接口的实现类
  • AuthenticationProvider: 主要用来进行认证操作的类 调用其中的authenticate()方法去进行认证操作
  • Authentication:Spring Security方式的认证主体
  • GrantedAuthority:对认证主题的应用层面的授权,含当前用户的权限信息,通常使用角色表示
  • UserDetails:构建Authentication对象必须的信息,可以自定义,可能需要访问DB得到
  • UserDetailsService:通过username构建UserDetails对象,通过loadUserByUsername根据userName获取UserDetail对象 (可以在这里基于自身业务进行自定义的实现 如通过数据库,xml,缓存获取等)

Springboot整合SpringSecurity入门_第1张图片

Springboot整合SpringSecurity入门_第2张图片

Springboot整合SpringSecurity入门_第3张图片

过滤器总结

  • WebAsyncManagerIntegrationFilter
  • SecurityContextPersistenceFilter
  • HeaderWriterFilter
  • CorsFilter
  • LogoutFilter
  • RequestCacheAwareFilter
  • SecurityContextHolderAwareRequestFilter
  • AnonymousAuthenticationFilter
  • SessionManagementFilter
  • ExceptionTranslationFilter
  • FilterSecurityInterceptor
  • UsernamePasswordAuthenticationFilter
  • BasicAuthenticationFilter

Springboot整合SpringSecurity入门_第4张图片

SpringSecurity测试环境部署

导入依赖

导入 thymeleaf依赖


    org.springframework.boot
    spring-boot-starter-thymeleaf

在application.properties 中关闭 thymeleaf 缓存

spring.thymeleaf.cache=false

创建静态页面

创建过个静态页面供SpringSecurity控制访问

分别在template目录下创建文件夹 views,在views中创建三个 level01、level02、level03包,然后分别在每个包下创建三个静态页面1.html、2.html、3.html

然后在每个静态页面填写不同的内容加以区分

1.html




    
    Title


    

level01-1.html


返回主页

创建 index.html




    
    Title


    

hello SpringSecurity


创建控制器

创建Controller 实现对各个页面的跳转操作

package com.jason.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;

/**
 * @authot jason_yan
 * @date 2020/6/18-9:08
 */
@Controller
public class IndexController {

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

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

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

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

Springboot整合SpringSecurity

导入依赖


    org.springframework.boot
    spring-boot-starter-security

此时启动服务器时,SpringSecurity 会拦截所有的请求,用户必须登录SpringSecurity 的 默认登录页面,才可以访问其他资源

账号:user

密码:控制台自动生成

创建SpringSecurity配置类

SecurityConfig配置类继承WebSecurityConfigurerAdapter

重写两个方法:

configure(HttpSecurity http):进行用户授权(验证某个用户是否有权限执行某个操作)

configure(AuthenticationManagerBuilder auth):进行用户认证(检测登录用户是否合法)

在配置类上添加 @EnableWebSecurity的作用:

​ 1: 加载WebSecurityConfiguration配置类, 配置安全认证策略。

​ 2: 加载AuthenticationConfiguration, 配置了认证信息。

package com.jason.controller.config;

import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

/**
 * @authot jason_yan
 * @date 2020/6/18-9:54
 */
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // 设置请求资源的权限(授权)
        http
                .authorizeRequests() // 对请求进行授权
                .antMatchers("/").permitAll() // 设置首页任何人都可访问
                .antMatchers("/level01/**").hasRole("doctor") // 指定要设置权限信息的地址和授权角色
                .antMatchers("/level02/**").hasRole("master") // 两个*代表目录的深度(任意深度)
                .antMatchers("/level03/**").hasRole("teacher")
                .and()
                .formLogin(); // 设置未授权的请求跳转 到 登录表单页面

    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        // 模拟假数据
        auth.inMemoryAuthentication()
                .withUser("zs").password("111").roles("doctor")
                .and()
                .withUser("ls").password("222").roles("master")
                .and()
                .withUser("ww").password("333").roles("teacher");
    }
}

测试以上配置:

1、当请求首页上的链接时,会跳转到SpringSecurity 默认登录页面,因为我们没有相应的权限访问该资源————.formLogin() 实现本次跳转

2、可以使用 zs、ls、ww等用户进行登录

3、登录成功后无法访问相对应的角色资源:报错 java.lang.IllegalArgumentException: There is no PasswordEncoder mapped for the id "null"

解决上述问题:在登录过程中,SpringSecurity处理的密码不能是明文密码,所以我们的密码需要 在认证方法中 进行对密码进行加密

@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {

    BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
    // 模拟假数据
    auth.inMemoryAuthentication()
        .passwordEncoder(bCryptPasswordEncoder) // 设置加密方式
        .withUser("zs").password(bCryptPasswordEncoder.encode("111")).roles("doctor")
        .and()
        .withUser("ls").password(bCryptPasswordEncoder.encode("222")).roles("master")
        .and()
        .withUser("ww").password(bCryptPasswordEncoder.encode("333")).roles("teacher");
}

以上即可实现相应的用户 访问相应的资源

设置用户访问权限不足的跳转页面

在SecurityConfig配置类的configure(HttpSecurity http)方法中

添加 当用户权限不足时 的访问路径

@Override
protected void configure(HttpSecurity http) throws Exception {

    // 设置请求资源的权限(授权)
    http
        .authorizeRequests() // 对请求进行授权
        ...
        .formLogin(); // 设置未授权请求跳转的登录表单页面

    http.exceptionHandling().accessDeniedPage("/no/auth"); // 用有访问权限的角色被访问拒绝后跳转的路径

}

控制器 实现跳转

@RequestMapping("/no/auth")
public String noAuth(){
    return "views/no-auth";
}

在views目录下创建 跳转的页面 no-auth.html




    
    Title


    

您的权限不足以访问此资源


返回主页

注销功能

在 SecurityConfig 配置类的 configure(HttpSecurity http) 方法中

开启注销功能

@Override
protected void configure(HttpSecurity http) throws Exception {

    ...
    
    http.logout()		//开启用户退出登录的功能
        .logoutSuccessUrl("/");	//设置成功退出登录后前往首页
    
    // 下方无代码

}

在index.html页面中添加 退出登录的请求链接地址


    

hello SpringSecurity


退出登录

...

SpringSecurity 整合 Thymeleaf

需要实现的功能:

​ 1、当用户未登录时——显示登录按钮

​ 2、当用户登录时——显示退出登录按钮

​ 3、当用户登录至页面时只显示相对应的权限链接

导入依赖


   org.thymeleaf.extras
   thymeleaf-extras-springsecurity5
   3.0.4.RELEASE

添加首页命名空间:xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity5"

并 修改 index.html 页面

要实现此功能必须关闭csrf功能:跨站请求伪造

在 SecurityConfig 配置类的 configure(HttpSecurity http) 方法中

@Override
protected void configure(HttpSecurity http) throws Exception {
 
 ...
     
	http.csrf().disable();
 
 // 下方无代码
}




    
    Title


    

hello SpringSecurity


name: role:

退出登录

...

实现当用户登录至页面时只显示相对应的权限链接




    
    Title


    

hello SpringSecurity


记住我功能

只要登录之后,关闭浏览器,依然可以保留登录状态

原因:

​ 登录成功后,服务器会为用户生成cookie并发送给浏览器保存

​ 以后用户登录会携带此cookie,只要通过检查就可以免登录了

​ 如果点击注销,则会删除相应用户的cookie

//定制请求的授权规则
@Override
protected void configure(HttpSecurity http) throws Exception {
	...
   
    http.rememberMe();  // 记住我
}

![image-20200618115148750](F:\项目学习\SpringBoot\springboot Security\image-20200618115148750.png)

自定义登录页面

在views目录下创建登录页面 login.html

PS:登录表单的提交方式必须是 post




    
    Title



用户登录页面


username:

password:

记住我

修改SecurityConfig 配置类的 configure(HttpSecurity http) 方法

protected void configure(HttpSecurity http) throws Exception {

    // 设置请求资源的权限(授权)
    http
        ...
        
        .formLogin()    // 设置未授权请求跳转的登录表单页面
        .loginPage("/toLogin").permitAll() // 指定登录页面地址且所有人都可以访问
        .usernameParameter("username") // 告诉SpringSecurity登录账号请求参数名(与表单一致)
        .passwordParameter("password") // 告诉SpringSecurity登录密码请求参数名(与表单一致)
        .loginProcessingUrl("/do/login") // 登录表单提交地址
        ;
    
		...
            
    http.rememberMe().rememberMeParameter("remember"); //开启记住我功能,参数与表单一致; // 记住我
}

控制器实现跳转

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

SecurityConfig 配置类 全部代码

package com.jason.controller.config;

import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

/**
 * @authot jason_yan
 * @date 2020/6/18-9:54
 */
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        // 设置请求资源的权限(授权)
        http
                .authorizeRequests() // 对请求进行授权
                .antMatchers("/").permitAll() // 设置首页任何人都可访问
                .antMatchers("/level01/**").hasRole("doctor") // 指定要设置权限信息的地址和授权角色
                .antMatchers("/level02/**").hasRole("master") // 两个*代表目录的深度(任意深度)
                .antMatchers("/level03/**").hasRole("teacher")
                .and()
                .formLogin()    // 设置未授权请求跳转的登录表单页面
                .loginPage("/toLogin").permitAll()    // 指定登录页面地址且所有人都可以访问
                .usernameParameter("username") // 告诉SpringSecurity登录账号请求参数名(与表单一致)
                .passwordParameter("password") // 告诉SpringSecurity登录密码请求参数名(与表单一致)
                .loginProcessingUrl("/do/login") // 登录表单提交地址
                ;

        http.exceptionHandling().accessDeniedPage("/no/auth"); // 用有访问权限的角色被访问拒绝后跳转的路径

        http.logout()     //开启用户退出登录的功能
            .logoutSuccessUrl("/");    //设置成功退出登录后前往主页

        http.csrf().disable(); // 关闭跨站请求伪造

        http.rememberMe().rememberMeParameter("remember"); //开启记住我功能,参数与表单一致; // 记住我
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {

        BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
        // 模拟假数据
        auth.inMemoryAuthentication()
                .passwordEncoder(bCryptPasswordEncoder) // 设置加密方式
                .withUser("zs").password(bCryptPasswordEncoder.encode("111")).roles("doctor")
                .and()
                .withUser("ls").password(bCryptPasswordEncoder.encode("222")).roles("master")
                .and()
                .withUser("ww").password(bCryptPasswordEncoder.encode("333")).roles("teacher");
    }
}

SpringSecurity 整合 数据库

待续...

你可能感兴趣的:(Springboot整合SpringSecurity入门)