spring security(密码编码器、授权,会话)

news2024/11/6 10:01:48

目录

密码编码器

授权决策

AffirmativeBased

ConsensusBased

UnanimousBased

授权

web授权

HttpSecurity常用方法及说明

方法授权

会话控制 

会话超时 

安全会话cookie


密码编码器

Spring Security为了适应多种多样的加密类型,又做了抽象,DaoAuthenticationProvider通过 PasswordEncoder接口进行密码的对比,而具体的密码对比细节取决于实现: 

可以看到,PasswordEncoder接口中一共三个方法:

  • encod方法:该方法用来给明文密码进行加密
  • matches方法:该方法用来进行密码对比
  • upgradeEncoding方法:该方法用来判断当前密码是否需要升级,默认返回false表示不需要升级

 Spring Security提供很多内置的PasswordEncoder,能够开箱即用,使用某种PasswordEncoder只需要进行如下声明即可,如下:

@Bean
    public PasswordEncoder passwordEncoder(){
        // 定义明文比较
        return NoOpPasswordEncoder.getInstance();
    }

PasswordEncoder中常见的实现类:

  • BCryptPasswordEncoder:使用BCrypt强哈希函数加密密码。
  • NoOpPasswordEncoder:不对密码进行加密,即明文存储密码。
  • Pbkdf2PasswordEncoder:使用PBKDF2强哈希函数加密密码。
  • SCryptPasswordEncoder:使用SCrypt强哈希函数加密密码。
  • StandardPasswordEncoder:使用SHA-256哈希函数加密密码。

授权决策

AccessDecisionManager采用投票的方式来确定是否能够访问受保护资源。

 通过上图可以看出,AccessDecisionManager中包含的一系列AccessDecisionVoter将会被用来对Authentication 是否有权访问受保护对象进行投票,AccessDecisionManager根据投票结果,做出最终决策。

AccessDecisionVoter 是一个接口,其中定义有三个方法,具体结构如下所示。

 

vote() 方法的返回结果会是 AccessDecisionVoter 中定义的三个常量之一。
  • ACCESS_GRANTED表示同意
  • ACCESS_DENIED表示拒绝
  • ACCESS_ABSTAIN表示弃权
如果一个 AccessDecisionVoter 不能判定当前Authentication是否拥有访问对应受保护对象的权限,则其 vote() 方法的返回值应当为弃权 ACCESS_ABSTAIN 。Spring Security内置了三个基于投票的 AccessDecisionManager 实现类如下,它们分别是
  • AffirmativeBased
  • ConsensusBased
  • UnanimousBased

AffirmativeBased

其逻辑是:

  1. 只要有AccessDecisionVoter的投票为ACCESS_GRANTED则同意用户进行访问;
  2. 如果全部弃权也表示通过;
  3. 如果没有一个人投赞成票,但是有人投反对票,则将抛出AccessDeniedException
Spring security 默认使用的是 AffirmativeBased

ConsensusBased

其逻辑是:
  1. 如果赞成票多于反对票则表示通过。
  2. 反过来,如果反对票多于赞成票则将抛出AccessDeniedException。
  3. 如果赞成票与反对票相同且不等于0,并且属性allowIfEqualGrantedDeniedDecisions的值为true(值默认为true),则表示通过,否则将抛出异常AccessDeniedException。
  4. 如果所有的AccessDecisionVoter都弃权了,则将视参数allowIfAllAbstainDecisions的值(值默认为false)而定,如果该值 为true则表示通过,否则将抛出异常AccessDeniedException。

UnanimousBased

它的逻辑与另外两种实现有点不一样,另外两种会一次性把受保护对象的配置属性全部传递 给AccessDecisionVoter进行投票,而UnanimousBased会一次只传递一个ConfifigAttribute给 AccessDecisionVoter进行投票。这也就意味着如果我们AccessDecisionVoter的逻辑是只要传递进来的 ConfifigAttribute中有一个能够匹配则投赞成票,但是放到UnanimousBased中其投票结果就不一定是赞成了。 UnanimousBased的逻辑具体来说是这样的:

  1. 如果受保护对象配置的某一个ConfifigAttribute被任意的AccessDecisionVoter反对了,则将抛出AccessDeniedException
  2. 如果没有反对票,但是有赞成票,则表示通过。
  3. 如果全部弃权了,则将视参数allowIfAllAbstainDecisions的值而定,true则通过,false则抛出 AccessDeniedException

Spring Security也内置一些投票者实现类如RoleVoterAuthenticatedVoterWebExpressionVoter等,可以自行查阅资料进行学习。

授权

授权的方式包括 web授权和方法授权,web授权是通过 url拦截进行授权,方法授权是通过 方法拦截进行授权。他 们都会调用accessDecisionManager进行授权决策,若为web授权则拦截器为FilterSecurityInterceptor;若为方法授权则拦截器为MethodSecurityInterceptor。如果同时通过web授权和方法授权则先执行web授权,再执行方法授权,最后决策通过,则允许访问资源,否则将禁止访问。

类关系如下:  

web授权

通过给 http.authorizeRequests() 添加多个子节点来定制需求到我们的URL,如下代码:

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.password.NoOpPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    //安全拦截机制(最重要)
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.csrf().disable()//屏蔽CSRF控制,即spring security不再限制CSRF
                .authorizeRequests()
                .antMatchers("/r/r1").hasAuthority("p1")//将资源与权限绑定
                .antMatchers("/r/r2").hasAuthority("p2")//将资源与权限绑定
                .antMatchers("/r/r3").hasRole("管理员")//将资源与角色绑定
                .antMatchers("/r/r4").hasAnyAuthority("p1","p2")//将资源与权限数组绑定
                .antMatchers("/r/**").authenticated()//所有/r/**的请求必须认证通过
                .anyRequest().permitAll()//除了/r/**,其它的请求可以访问
                .and()
                .formLogin()//允许表单登录
                .loginPage("/login-view")//指定我们自己的登录页,spring security以重定向方式跳转到/login-view
                .loginProcessingUrl("/login")//指定登录处理的URL,也就是用户名、密码表单提交的目的路径
                .successForwardUrl("/login-success");//指定登录成功后的跳转URL

        // 自定义会话控制
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);

        // 自定义退出
        http.logout()
                .logoutUrl("/logout")// 退出的url
                .logoutSuccessUrl("/login-view");// 退到/login-view
    }
}

注:规则的顺序是重要的,更具体的规则应该先写

HttpSecurity常用方法及说明

方法说明
authenticated()保护URL,需要用户登录
permitAll()指定URL无需保护,一般应用与静态资源文件
hasRole(String role)限制单个角色访问,角色将被增加 “ROLE_” .所以”ADMIN” 将和 “ROLE_ADMIN”进行比较.
hasAuthority(String authority)限制单个权限访问
hasAnyRole(String… roles)允许多个角色访问
hasAnyAuthority(String… authorities) 允许多个权限访问
access(String attribute)该方法使用 SpEL表达式, 所以可以创建复杂的限制
hasIpAddress(String ipaddressExpression)限制IP地址或子网
openidLogin()用于基于 OpenId 的验证
headers()将安全标头添加到响应
cors()配置跨域资源共享( CORS )
sessionManagement()允许配置会话管理
portMapper()    允许配置一个PortMapper(HttpSecurity#(getSharedObject(class))),其他提供SecurityConfigurer的对象使用 PortMapper 从 HTTP 重定向到 HTTPS 或者从 HTTPS 重定向到 HTTP。默认情况下,Spring Security使用一个PortMapperImpl映射 HTTP 端口8080到 HTTPS 端口8443,HTTP 端口80到 HTTPS 端口443
jee()配置基于容器的预认证。 在这种情况下,认证由Servlet容器管理
x509()配置基于x509的认证
rememberMe允许配置“记住我”的验证
authorizeRequests()允许基于使用HttpServletRequest限制访问
requestCache()允许配置请求缓存
exceptionHandling()允许配置错误处理
securityContext()在HttpServletRequests之间的SecurityContextHolder上设置SecurityContext的管理。 当使用WebSecurityConfigurerAdapter时,这将自动应用
servletApi()将HttpServletRequest方法与在其上找到的值集成到SecurityContext中。 当使用WebSecurityConfigurerAdapter时,这将自动应用
csrf()添加 CSRF 支持,使用WebSecurityConfigurerAdapter时,默认启用
logout()添加退出登录支持。当使用WebSecurityConfigurerAdapter时,这将自动应用。默认情况是,访问URL”/ logout”,使HTTP Session无效来清除用户,清除已配置的任何#rememberMe()身份验证,清除SecurityContextHolder,然后重定向到”/login?success”
anonymous()允许配置匿名用户的表示方法。 当与WebSecurityConfigurerAdapter结合使用时,这将自动应用。 默认情况下,匿名用户将使用org.springframework.security.authentication.AnonymousAuthenticationToken表示,并包含角色 “ROLE_ANONYMOUS”
formLogin()指定支持基于表单的身份验证。如果未指定FormLoginConfigurer#loginPage(String),则将生成默认登录页面
oauth2Login()根据外部OAuth 2.0或OpenID Connect 1.0提供程序配置身份验证
requiresChannel()配置通道安全。为了使该配置有用,必须提供至少一个到所需信道的映射
httpBasic()配置 Http Basic 验证
addFilterAt()在指定的Filter类的位置添加过滤器

方法授权

 Spring Security2.0版 本开始,它支持服务层方法的安全性的支持。主要有@PreAuthorize,@PostAuthorize, @Secured三类注解。

首先要开启Spring Security的 Secured、pre、Post 注解,在配置类上添加此注解

@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)

然后在controller中根据需求使用对资源授权,实例如下:

@RestController
public class LoginController {

    @RequestMapping(value = "/login-success",produces = {"text/plain;charset=UTF-8"})
    public String loginSuccess(){
        //提示具体用户名称登录成功
        return " 登录成功";
    }

    /**
     * 测试资源1
     * @return
     */
    @GetMapping(value = "/r/r1",produces = {"text/plain;charset=UTF-8"})
    @PreAuthorize("hasAuthority('p1')")//拥有p1权限才可以访问
    public String r1(){
        return " 访问资源1";
    }

    /**
     * 测试资源2
     * @return
     */
    @GetMapping(value = "/r/r2",produces = {"text/plain;charset=UTF-8"})
    @PreAuthorize("hasAuthority('p2')")//拥有p2权限才可以访问
    public String r2(){
        return " 访问资源2";
    }
}

其@PreAuthorize中的参数与HttpSecurity的IPA相差无几

会话控制 

我们可以通过以下选项准确控制会话何时创建以及Spring Security如何与之交互:

机制描述
always如果没有session存在就创建一个
ifRequired如果需要就创建一个Session(默认)登录时
never
SpringSecurity 将不会创建 Session ,但是如果应用中其他地方创建了 Session ,那么 Spring
Security 将会使用它。
statelessSpringSecurity将绝对不会创建Session,也不使用Session

 通过在继承WebSecurityConfigurerAdapter类来进行如下配置:

@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED);
    }
}
  • 若选用never,则指示Spring Security对登录成功的用户不创建Session了,但若你的应用程序在某地方新建了 session,那么Spring Security会用它的。
  • 若使用stateless,则说明Spring Security对登录成功的用户不会创建Session了,你的应用程序也不会允许新建 session。并且它会暗示不使用cookie,所以每个请求都需要重新进行身份验证。这种无状态架构适用于REST API及其无状态认证机制。

会话超时 

可以再sevlet容器中设置Session的超时时间,如下设置Session有效期为3600s 

spring boot 配置文件:

server.servlet.session.timeout=3600s

 session超时之后,可以通过Spring Security 设置跳转的路径。

http.sessionManagement()
.expiredUrl("/login‐view?error=EXPIRED_SESSION")
.invalidSessionUrl("/login‐view?error=INVALID_SESSION");

安全会话cookie

我们可以使用 httpOnly secure 标签来保护我们的会话 cookie
  • httpOnly:如果为true,那么浏览器脚本将无法访问cookie
  • secure:如果为true,则cookie将仅通过HTTPS连接发送
spring boot 配置文件:
server.servlet.session.cookie.http‐only=true
server.servlet.session.cookie.secure=true

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/585193.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

虚拟机配置

配置虚拟机网络 创建虚拟机 20G 4G内存 初始化用户名和密码 zhao 123456 克隆拷贝2个虚拟机 配置内存为2G 修改主机名和固定IP hostnamectl set-hostname node1 hostnamectl set-hostname node2 vim /etc/sysconfig/network-scripts/ifcfg-ens33 systemctl stop network s…

渗透测试辅助工具箱

0x01 说明 渗透测试辅助工具箱 运行条件:jdk8 双击即可运行 反弹shell,命令生成器,自动编码,输入对应IP端口即可,实现一劳永逸,集成一些小工具,辅助渗透,提高效率 输入框说明 L…

TDengine 报错 failed to connect to server, reason: Unable to establish connection

一、前文 TDengine 入门教程——导读 二、遇到问题 taos 命令行(CLI)连接不上,进不去。 [rootiZ2ze30dygwd6yh7gu6lskZ ~]# taos Welcome to the TDengine Command Line Interface, Client Version:3.0.0.1 Copyright (c) 2022 by TDengine…

基于Azure实现Java访问OpenAI

之前使用了Java代码访问OpenAI:OpenAI注册以及Java代码调用_雨欲语的博客-CSDN博客但是需要vpn才能访问,现在可以基于微软的Azure访问OpenAI,不再需要vpn,官方文档:快速入门 - 开始通过 Azure OpenAI 服务使用 ChatGPT…

【国产虚拟仪器】基于JFM7K325T(复旦微FPGA)的高速数据采集平台

板卡概述 XM714是自主研制的一款5路HD-SDI视频采集图像处理平台,该平台采用上海复旦微的高性能Kintex系列FPGA加上华为海思的高性能视频处理器HI3531DV200来实现。 华为海思的HI3531DV200是一款集成了ARM A53四核处理器性能强大的神经网络引擎,支持多种…

python:容器:字符串——常用操作

字符串[下标]根据下标索引取出特定位置字符字符串.index(字符串)查找给定字符的第一个匹配项的下标字符串.replace(字符串1,字符串2) 将字符串内的全部字符串1,替换为字符串2 不会修改原字符串,而是得到一个新的 字符串.split(字符串) 按照给定字符串&am…

[高光谱]使用PyTorch的dataloader加载高光谱数据

本文实验的部分代码参考 Hyperspectral-Classificationhttps://github.com/eecn/Hyperspectral-Classification如果对dataloader的工作原理不太清楚可以参见 [Pytorch]DataSet和DataLoader逐句详解https://blog.csdn.net/weixin_37878740/article/details/129350390?spm1001…

使用Nextcloud搭建私人云盘,并内网穿透实现公网远程访问

文章目录 摘要视频教程1. 环境搭建2. 测试局域网访问3. 内网穿透3.1 ubuntu本地安装cpolar3.2 创建隧道3.3 测试公网访问 4 配置固定http公网地址4.1 保留一个二级子域名4.1 配置固定二级子域名4.3 测试访问公网固定二级子域名 转载自cpolar极点云的文章:使用Nextcl…

好程序员:如果你从6月份开始学Java编程......

现在学习Java编程还来得及?好程序员可以明确的告诉你:当然了~新手入门快,非常容易学。Java计算机语言也是一门面向对象的语言,更加符合人类的思想,所求皆对象,并没有指针等一些难理解的知识。Java覆盖面宽、…

2023最新软件测试面试题大全(包含答案)

前言 在我认为,对于测试面试以及进阶的最佳学习方法莫过于刷题博客书籍视频总结,前几者博主将淋漓尽致地挥毫于这篇博客文章中,至于总结在于个人,实际上越到后面你会发现面试并不难,其次就是在刷题的过程中有没有去思…

Power BI许可证差异(免费、Pro、PPU、Embedded、Premium)

不可否认,在商业BI软件中Power BI是最强大的,在2023年的Gartner的魔力象限中Power BI又是第一名Microsoft named a Leader in the 2023 Gartner Magic Quadrant™ for Analytics and BI PlatformsI[1] image.png 目前还没有使用Power BI的,甚…

Microsoft Build 发布,开发者可能关注的重点→

又是一年一度的 Microsoft Build 了,你有和我一样熬夜看了吗?如果没有,那么你就错过了一场精彩的技术盛宴。本次的 Microsoft Build,有非常多的干货,围绕打造 Copilot 应用展开。我会将基于 Data AI 比较重要的内容列…

2.1. 类与对象

在 Java 中,类和对象是面向对象编程的基本构建块。类是一种模板,用于定义对象的属性和行为。对象是类的实例,具有类定义的属性和行为。 2.1.1. 类的定义 要定义一个类,可以使用以下语法: class ClassName {// 成员变…

Java学习路线(17)——日志框架

一、日志技术概述 (1)概念: 日志是一种将系统运行信息封装至文件的一种记录载体。 (2)优势: 输出语句日志技术输出位置只能是控制台文件或数据库取消日志需要修改代码达成无需修改代码多线程性能较差性能较…

AcrelEMS企业微电网能效管理系统-强化电力需求侧管理,缓解电力系统峰值压力

摘要 近年来全国用电负荷特别是居民用电负荷的快速增长,全国范围内夏季、冬季用电负荷“双峰”特征日益突出,极端气候现象多发增加了电力安全供应的压力。具有随机性、波动性、间歇性特征的可再生能源大规模接入电网对电力系统的稳定性带来新的挑战&…

财务共享服务中心建设流程是什么样的?

财务共享是当今众多企业在数智化转型道路上的首选模式,财务共享服务中心由于具备“标准化、流程化、资源共享、信息化”的特点,一改传统财务分散的运作模式,将资源集中共享,大大提升了财务管理效率,也为企业管理打下良…

Loki安装使用方式

Distributor 收到 HTTP 请求,用于存储流数据 通过 hash 环对数据流进行 hash Distributor将数据流发送到对应的Ingester及其副本上 Ingester 新建 Chunk 或将数据追加到已有Chunk 上 Distributor通过 HTTP连接发送响应信息 Loki 日志系统由以下3个部分组成&#xf…

每日一题——删除字符串中的所有相邻重复项

每日一题 删除字符串中的所有相邻重复项 题目链接 思路 这是一道用栈解决的典型题目 我们先来看看栈的基本性质: 栈:是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素的操作。进行数据插入和删除操作的一端称为栈顶&#xff0c…

解决Github上传或者下载时失败的问题

总是出现push不到GitHub的问题, 这里来记录一下每次的解决方法 文章目录 2023年05月28日出现问题2023年05月28日再次出现问题2023年05月29日出现问题 2023年05月28日出现问题 push代码时出现如下图所示的错误 Failed to connect to 127.0.0.1 port 1080 after 2052 ms: Conne…

08.Stack和Queue

栈:先进后出 队列:先进先出 JVM的栈就是平常所说的一块内存。 此处所说的栈是数据结构 1. 栈(Stack) 1.1 概念 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈 顶&…