SpringSecurity认证基本原理与认证2种方式_spring security 多种认证_程序小黑马的博客-程序员宝宝

技术标签: 安全  http  https  Spring  

  • 2.1 HttpBasic认证

  • 2.2  formLogin登录认证模式

  • 2.3 表单认证

  • 2.3.1 在config包下编写SecurityConfiguration配置类

  • 2.3.2 解决静态资源被拦截问题

  • 改造登录

  • 2.4 基于数据库实现认证功能

  • 2.5 密码加密验证

Spring Security功能的实现主要是由一系列过滤器相互配合完 成。也称之为过滤器链,Spring Security默认加载15个过滤器, 但是随着配置可以增加或者删除一些过滤器.

一、过滤器链介绍

图片

image-20211124155050759

过滤器是一种典型的AOP思想,下面简单了解下这些过滤器链,后续再源码剖析中在涉及到过滤器链在 仔细讲解

1.org.springframework.security.web.context.request.async.WebAsyncManagerIntegrationFilter

根据请求封装获取WebAsyncManager,从WebAsyncManager获取/注册的安全上下文可调 用处理拦截器

2.org.springframework.security.web.context.SecurityContextPersistenceFilter

SecurityContextPersistenceFilter主要是使用SecurityContextRepository在session中保存 或更新一个SecurityContext,并将SecurityContext给以后的过滤器使用,来为后续fifilter 建立所需的上下文。SecurityContext中存储了当前用户的认证以及权限信息。

3.org.springframework.security.web.header.HeaderWriterFilter

向请求的Header中添加相应的信息,可在http标签内部使用security:headers来控制

4.org.springframework.security.web.csrf.CsrfFilter

csrf又称跨域请求伪造,SpringSecurity会对所有post请求验证是否包含系统生成的csrf的 token信息,如果不包含,则报错。起到防止csrf攻击的效果。

5.org.springframework.security.web.authentication.logout.LogoutFilter

匹配URL为/logout的请求,实现用户退出,清除认证信息。

6.org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter

表单认证操作全靠这个过滤器,默认匹配URL为/login且必须为POST请求

7.org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter

如果没有在配置文件中指定认证页面,则由该过滤器生成一个默认认证页面。

8.org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter

由此过滤器可以生产一个默认的退出登录页面

9.org.springframework.security.web.authentication.www.BasicAuthenticationFilter

此过滤器会自动解析HTTP请求中头部名字为Authentication,且以Basic开头的头信息

10.org.springframework.security.web.savedrequest.RequestCacheAwareFilter

通过HttpSessionRequestCache内部维护了一个RequestCache,用于缓存 HttpServletRequest

11.org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter

针对ServletRequest进行了一次包装,使得request具有更加丰富的API

12.org.springframework.security.web.authentication.AnonymousAuthenticationFilter

当SecurityContextHolder中认证信息为空,则会创建一个匿名用户存入到 SecurityContextHolder中。spring security为了兼容未登录的访问,也走了一套认证流程, 只不过是一个匿名的身份。

13.org.springframework.security.web.session.SessionManagementFilter

securityContextRepository限制同一用户开启多个会话的数量

14.org.springframework.security.web.access.ExceptionTranslationFilter

异常转换过滤器位于整个springSecurityFilterChain的后方,用来转换整个链路中出现的异 常

15.org.springframework.security.web.access.intercept.FilterSecurityInterceptor

获取所配置资源访问的授权信息,根据SecurityContextHolder中存储的用户信息来决定其 是否有权限。

二、认证方式

2.1 HttpBasic认证

HttpBasic登录验证模式是Spring Security实现登录验证最简单的一种方式,也可以说是最简陋 的一种方式。它的目的并不是保障登录验证的绝对安全,而是提供一种“防君子不防小人”的登录验 证。

在使用的Spring Boot早期版本为1.X版本,依赖的Security 4.X版本,那么就无需任何配置,启动 项目访问则会弹出默认的httpbasic认证。现在使用的是spring boot2.0以上版本(依赖Security 5.X版本),HttpBasic不再是默认的验证模式,在spring security 5.x默认的验证模式已经是表单 模式。

HttpBasic模式要求传输的用户名密码使用Base64模式进行加密。如果用户名是 “admin” , 密码是“ admin”,则将字符串"admin:admin" 使用Base64编码算法加密。加密结果可能是:YWtaW46YWRtaW4=。HttpBasic模式真的是非常简单又简陋的验证模式,Base64的加密算法是 可逆的,想要破解并不难

图片

image-20211124161756023

2.2  formLogin登录认证模式

Spring Security的HttpBasic模式,该模式比较简单,只是进行了通过携带Http的Header进行 简单的登录验证,而且没有定制的登录页面,所以使用场景比较窄。对于一个完整的应用系统,与 登录验证相关的页面都是高度定制化的,非常美观而且提供多种登录方式。这就需要Spring Security支持我们自己定制登录页面, spring boot2.0以上版本(依赖Security 5.X版本)默认会生 成一个登录页面.

2.3 表单认证

2.3.1 在config包下编写SecurityConfiguration配置类

/**
 * @author wuzhixuan
 * @version 1.0.0
 * @ClassName SecurityConfiguration.java
 * @Description Security配置类
 * @createTime 2021年11月24日 16:35:00
 */

@Configuration
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        super.configure(auth);
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        super.configure(web);
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        /*http.httpBasic() // 开启base验证
                .and().authorizeRequests().anyRequest().authenticated(); //所有请求都需要登录认证才能访问*/
        http.formLogin().loginPage("/toLoginPage") // 开启表单验证
                .and().authorizeRequests()
                .antMatchers("/toLoginPage").permitAll() // 放行当前请求
                .anyRequest().authenticated(); //所有请求都需要登录认证才能访问;
    }
}

图片

image-20211124164629344

重启服务发现css,js等静态文件没有成功加载

2.3.2 解决静态资源被拦截问题

@Override
public void configure(WebSecurity web) throws Exception {
    //解决静态资源被拦截的问题
    web.ignoring().antMatchers("/css/**", "/js/**", "/images/**", "/favicon.ico");
}

Spring Security 中,安全构建器 HttpSecurity 和 WebSecurity 的区别是 :

  • WebSecurity 不仅通过 HttpSecurity 定义某些请求的安全控制,也通过其他方式定义其他某些 请求可以忽略安全控制;

  • HttpSecurity 仅用于定义需要安全控制的请求(当然 HttpSecurity 也可以指定某些请求不需要 安全控制);

  • 可以认为 HttpSecurity 是 WebSecurity 的一部分, WebSecurity 是包含 HttpSecurity 的更大 的一个概念;

  • 构建目标不同

  • WebSecurity 构建目标是整个 Spring Security 安全过滤器 FilterChainProxy`,

  • HttpSecurity 的构建目标仅仅是 FilterChainProxy 中的一个 SecurityFilterChain 。

图片

image-20211124170821308

改造登录

protected void configure(HttpSecurity http) throws Exception {
    /*http.httpBasic() // 开启base验证
            .and().authorizeRequests().anyRequest().authenticated(); //所有请求都需要登录认证才能访问*/
    http.formLogin() // 开启表单验证
            .loginPage("/toLoginPage") // 自定义登录页面
            .loginProcessingUrl("/login") // 登录请求url
            .usernameParameter("username")  // 修改自定义表单name值
            .passwordParameter("password")
            .successForwardUrl("/") // 登录成功跳转的路径
            .and().authorizeRequests()
            .antMatchers("/toLoginPage").permitAll() // 放行当前请求
            .anyRequest().authenticated(); //所有请求都需要登录认证才能访问;
    // 关闭csrf防护
    http.csrf().disable();
    // 允许iframe加载页面
    http.headers().frameOptions().sameOrigin();
}

发现行内框架iframe这里出现问题了. Spring Security下,X-Frame-Options默认为DENY,非Spring Security环境下,X-Frame-Options的默认大多也是DENY,这种情况下,浏览器拒绝当前页面加载任何 Frame页面,设置含义如下:

  • DENY:浏览器拒绝当前页面加载任何Frame页面 此选择是默认的.

  • SAMEORIGIN:frame页面的地址只能为同源域名下的页面

图片

image-20211124171005902

设置之后看到成功展示了

2.4 基于数据库实现认证功能

之前我们所使用的用户名和密码是来源于框架自动生成的, 那么我们如何实现基于数据库中的用户名和 密码功能呢? 要实现这个得需要实现security的一个UserDetailsService接口, 重写这个接口里面 loadUserByUsername即可

  • 编写MyUserDetailsService并实现UserDetailsService接口,重写loadUserByUsername方法
public class MyUserDetailsService implements UserDetailsService {

    @Autowired
    private UserService userService;

    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
        User user = userService.findByUsername(username);
        if (user == null) {
            throw new UsernameNotFoundException(username);// 用户名没有找到
        }
        // 先声明一个权限集合, 因为构造方法里面不能传入null
        Collection<? extends GrantedAuthority> authorities = new ArrayList<>();

        return new org.springframework.security.core.userdetails.User(username,
                "{noop}" + user.getPassword(),// {noop}表示不加密认证
                true, // 用户是否启用 true 代表启用
                true,// 用户是否过期 true 代表未过期
                true,// 用户凭据是否过期 true 代表未过期
                true,// 用户是否锁定 true 代表未锁定
                authorities
                );
    }
}
  • 在SecurityConfiguration配置类中指定自定义用户认证
/**
 * 身份验证管理器
 * @param auth
 * @throws Exception
 */
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
    auth.userDetailsService(myUserDetailsService);
}

2.5 密码加密验证

在基于数据库完成用户登录的过程中,我们所是使用的密码是明文的,规则是通过对密码明文添加 {noop} 前缀。那么下面 Spring Security 中的密码编码进行一些探讨。

Spring Security 中 PasswordEncoder 就是我们对密码进行编码的工具接口。该接口只有两个功能:一个是匹配验证。另一个是密码编码。

图片

image-20211124172444242

  • BCrypt算法介绍

BCrypt强哈希方法 每次加密的结果都不一样,所以更加的安全。

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接:https://blog.csdn.net/wuzhixuana/article/details/121927748

智能推荐

LSGO——LeetCode实战(数组系列): 89题 格雷编码 (Gray Code)_schwamaths的博客-程序员宝宝

格雷编码是一个二进制数字系统,在该系统中,两个连续的数值仅有一个位数的差异。给定一个代表编码总位数的非负整数 n,打印其格雷编码序列。格雷编码序列必须以 0 开头。示例 1:输入: 2输出: [0,1,3,2]解释:00 - 001 - 111 - 310 - 2对于给定的 n,其格雷编码序列并不唯一。例如,[0,2,3,1] 也是一个有效的格雷编码序列。00 - 010...

拓扑排序(java实现)_脸白大叔的博客-程序员宝宝

拓扑排序是判断有向图是否有环的基础算法   这是节点的beanpublic class Node { public String name; //节点名字 public Integer indegree; //入度个数 public List&amp;lt;Node&amp;gt; child=new ArrayList&amp;lt;Node&amp;gt;();//所指向的几点 ...

关于Vcc和Vdd的区别_荷兰风车的博客-程序员宝宝

<br />一、解释<br />  VCC:C=circuit 表示电路的意思, 即接入电路的电压;<br />  VDD:D=device 表示器件的意思, 即器件内部的工作电压;<br />  VSS:S=series 表示公共连接的意思,通常指电路公共接地端电压。<br />  二、说明<br />  1、对于数字电路来说,VCC是电路的供电电压,VDD是芯片的工作电压(通常Vcc>Vdd),VSS是接地点。<br />  2、有些IC既有VDD引脚又有VCC引脚,说明这种器件自身带有电压转换功能。<

6-如何设计一个便宜的线性稳压电源_星雨流星天的博客-程序员宝宝

本节课通过对DC-AC门电路设计成本出发,将KBJ407与LM7805在通过电路设计方面来降低成本,因为买现成的电路模块,会增加成本KBJ407可以通过4个整流二极管的电路设计,达到等效二极管分P区和N区,P区为阳极,N区为阴极,一般T0 - 22型的二极管,带环的为阴极,不带环都为阳极,应阳进阴出二极管的阳极标为A,阴极标为K二极管有多种连接方式http://www.elec...

Win10 ubantu 双系统 UEFI BIOS模式安装教程_愚人越的博客-程序员宝宝

一、下载ultraISO,Ubuntu镜像,官网下载,制作Ubantu启动U盘,二、将U盘插到电脑上,右键‘开始’找到磁盘管理,找到一个空闲的磁盘,格式化,压缩卷,不少于60G三、进入BIOS,win10下‘设置→恢复→立即重启→疑难→高级→UEFI设置→重启’,修改security boot 为disabled,找到boot enter进入 找到优先项,设置USB HDD为第一项,‘+,-’移动...

随便推点

Android利用ant将多个jar包合并成一个jar包_一路奔跑94的博客-程序员宝宝

做项目的时候(Eclipse),看到自己的libs文件夹下的jar包越来越多(引入第三方的库),同时也就出现了65536的问题,看了这一篇博客http://my.oschina.net/u/992018/blog/354513说是要将jar包利用ant转化成1个jar包,但是这篇博客的没有1、AntApache Ant是一个基于Java的生成工具。据最初的创始人James Duncan D...

CentOS7 配置NAT服务器以及端口映射_运维花絮的博客-程序员宝宝

https://blog.csdn.net/yhjay88/article/details/73178872?utm_source=itdadao&amp;amp;utm_medium=referralhttps://blog.csdn.net/qq_42197986/article/details/82778520

004_wz_bbk_用GCC编译第一个C程序及多文件编程_王泽的随笔的博客-程序员宝宝

Compiling a Simple C ProgramThe classic example program for the C language is:#include &lt;stdio.h&gt;int main(void){printf("hello world!\n"); return 0;}To compile the file with gcc,use the f...

Python科学计算初探——余弦相似度_python 向量余弦相似度_肖永威的博客-程序员宝宝

  SciPy是世界上著名的Python开源科学计算库,建立在Numpy之上。它增加的功能包括数值积分、最优化、统计和一些专用函数。例如线性代数、常微分方程数值求解、信号处理、图像处理、稀疏矩阵等等。安装科学计算包SciPy  由于SciPy库在Windows下使用pip intall安装失败(网上资料说的),所以需要寻找第三方(Unofficial Windows Binaries ...

Day05——Java基础知识_string sa = new string_明天也有晚霞嘛的博客-程序员宝宝

Day05——Java基础知识注释单行注释:只能注释当前行,以//开始,直到本行结束//单行注释多行注释:注释一段文字/*多行注释注释并不会被计算机编译注释是为了提高程序代码的可读性*/文档注释:(又称 说明注释)用于生产API文档,配合JavaDoc。说明注释在程序中嵌入关于程序的信息。可以使用 JavaDoc 工具软件来生成信息,并输出到HTML文件中,使你更加方便的记录你的程序信息。以**/**** 开始,以***/**结束。/*** 这个类演示了文档注释

modelsim与quartus仿真的区别_qq_40946355的博客-程序员宝宝

1.器件延迟modelsim没有明显的器件延迟,而quartus器件延迟明显2.信号采样点当信号在时钟沿发生变化时,modelsim采样时钟沿之后的信号,quartus采样时钟沿之前的信号。

推荐文章

热门文章

相关标签