spring security

// 注解作用域
@Retention(RetentionPolicy.RUNTIME)
// 使用位置
@Target(ElementType.METHOD)
// 权限校验注解
@PreAuthorize("hasAuthority('SCOPE_message:read')")
public @interface HasMessageRead {}  // 定义一个注解
@PreAuthorize("hasAuthority('SCOPE_{scope}')")

X.509 身份验证过滤器用于基于 X.509 证书对客户端进行身份验证。X.509 是一种广泛使用的公钥基础设施(PKI)标准,用于创建和管理数字证书

Servlet 身份验证架构

SecurityContextHolder——是Spring Security 存储经过身份验证的SecurityContextHolder人员的详细信息的地方。

SecurityContext - 从中​​获得SecurityContextHolder并包含Authentication当前经过身份验证的用户的。

身份验证——可以是输入,以AuthenticationManager提供用户提供的用于身份验证的凭据或当前用户的凭据SecurityContext。

GrantedAuthority-授予主体的权限Authentication(即角色、范围等)

AuthenticationManager——定义 Spring Security 的过滤器如何执行身份验证的API 。

ProviderManager——最常见的实现AuthenticationManager。

AuthenticationProvider - 用于ProviderManager执行特定类型的身份验证。

请求凭证AuthenticationEntryPoint- 用于从客户端请求凭证(即重定向到登录页面、发送响应WWW-Authenticate等)

AbstractAuthenticationProcessingFilter - 用于身份验证的基础Filter。这也很好地说明了身份验证的高级流程以及各部分如何协同工作。

核心逻辑使用

SecurityContext context = SecurityContextHolder.createEmptyContext(); 
Authentication authentication =
    new TestingAuthenticationToken("username", "password", "ROLE_USER"); 
context.setAuthentication(authentication);

SecurityContextHolder.setContext(context);

Authentication接口在 Spring Security 中有两个主要用途:

AuthenticationManager提供用户提供的用于验证身份的凭据的输入。在此场景中使用时,isAuthenticated()返回false。

表示当前已认证的用户。你可以Authentication从SecurityContext获取当前用户。

包含Authentication:

principal:标识用户。使用用户名/密码进行身份验证时,这通常是 的一个实例UserDetails。

credentials:通常是密码。在很多情况下,用户认证后会清除密码,以确保不泄露。

authorities:GrantedAuthority实例是授予用户的高级权限。两个示例是角色和范围。

GrantedAuthority实例是授予用户的高级权限。两个示例是角色和范围。

您可以GrantedAuthority从Authentication.getAuthorities()方法中获取实例。此方法提供Collection对象GrantedAuthority。GrantedAuthority毫无疑问,是授予主体的权限。此类权限通常是“角色”,例如ROLE_ADMINISTRATOR或ROLE_HR_SUPERVISOR。这些角色稍后将配置为 Web 授权、方法授权和域对象授权。Spring Security 的其他部分将解释这些权限并期望它们存在。当使用基于用户名/密码的身份验证时,GrantedAuthority实例通常由 加载UserDetailsService。

通常,GrantedAuthority对象是应用程序范围的权限。它们并不特定于给定的域对象。因此,您不太可能拥有GrantedAuthority表示对对象编号 54 的权限Employee,因为如果有数千个这样的权限,您将很快耗尽内存(或者,至少会导致应用程序花费很长时间来验证用户身份)。当然,Spring Security 专门设计用于处理这种常见需求,但您应该使用项目的域对象安全功能来实现此目的。

AuthenticationManager是定义 Spring Security 的过滤器如何执行身份验证的 API 。Authentication返回的 随后由调用 的控制器(即Spring Security 的实例)在SecurityContextHolder上设置。如果您未与 Spring Security 的实例集成,则可以直接设置,而不必使用。FiltersAuthenticationManagerFiltersSecurityContextHolderAuthenticationManager

虽然的实现AuthenticationManager可以是任何东西,但最常见的实现是ProviderManager。

权限

Spring Security 提供了强大的权限和访问控制机制,可以很好地处理应用程序范围的权限。对于具体的域对象(如对特定 Employee 的访问权限),Spring Security 推荐使用域对象安全功能,而不是直接使用 GrantedAuthority。这是因为 GrantedAuthority 通常用于定义全局的角色和权限,而不是特定对象的权限。

Spring Security 的处理机制
全局权限控制(GrantedAuthority):

GrantedAuthority 对象用于定义应用程序范围内的权限和角色。通常,这些权限不针对特定域对象,而是针对整个应用的功能进行控制。
例如,ROLE_ADMIN 和 ROLE_USER 是典型的 GrantedAuthority,用于控制用户是否有管理权限或普通用户权限。
域对象安全(Domain Object Security):

对于需要细粒度控制的场景,比如对特定资源(如某个特定的 Employee)的访问权限,Spring Security 提供了域对象安全的功能。
通过使用方法安全性和 ACL(Access Control List),可以实现对具体对象的权限控制。
域对象安全的实现

  1. 方法级别安全性
    通过方法级别的安全注解(如 @PreAuthorize 和 @PostAuthorize),可以基于业务逻辑进行权限控制。例如,检查用户是否有权访问特定对象。
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;

@Service
public class EmployeeService {

    @PreAuthorize("hasPermission(#id, 'com.example.Employee', 'read')")
    public Employee getEmployeeById(Long id) {
        // 获取并返回 Employee 对象
    }
}

在上面的例子中,@PreAuthorize 注解用于在方法执行前检查用户是否有权限读取特定的 Employee 对象。

  1. 使用 ACL(访问控制列表)
    Spring Security 提供了一个 ACL 模块,可以用于细粒度的域对象访问控制。ACL 允许你为每个域对象指定权限,并将这些权限与用户或角色关联。

配置 ACL:

引入依赖:
xml

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

配置 ACL 数据源:
配置 DataSource、JdbcMutableAclService 等必要的 Bean。

@Bean
public LookupStrategy lookupStrategy(DataSource dataSource) {
    return new BasicLookupStrategy(dataSource, aclCache(), aclAuthorizationStrategy(), new ConsoleAuditLogger());
}

@Bean
public JdbcMutableAclService aclService(DataSource dataSource) {
    return new JdbcMutableAclService(dataSource, lookupStrategy(dataSource), aclCache());
}

@Bean
public AclCache aclCache() {
    return new EhCacheBasedAclCache(ehCacheFactoryBean().getObject(), permissionGrantingStrategy(), aclAuthorizationStrategy());
}

使用 ACL:
通过 AclService 来管理和查询域对象的权限。

import org.springframework.security.acls.domain.BasePermission;
import org.springframework.security.acls.model.MutableAcl;
import org.springframework.security.acls.model.ObjectIdentity;
import org.springframework.security.acls.model.ObjectIdentityImpl;
import org.springframework.security.acls.model.Sid;
import org.springframework.security.acls.model.PrincipalSid;
import org.springframework.stereotype.Service;

@Service
public class AclManager {

    private final JdbcMutableAclService aclService;

    public AclManager(JdbcMutableAclService aclService) {
        this.aclService = aclService;
    }

    public void grantPermission(Long employeeId, String username, Permission permission) {
        ObjectIdentity oi = new ObjectIdentityImpl(Employee.class, employeeId);
        MutableAcl acl = aclService.createAcl(oi);
        Sid sid = new PrincipalSid(username);
        acl.insertAce(acl.getEntries().size(), permission, sid, true);
        aclService.updateAcl(acl);
    }
}

总结
Spring Security 提供了两种主要机制来处理权限控制:

GrantedAuthority 用于全局权限和角色管理。
域对象安全(Domain Object Security),通过方法安全性和 ACL,实现对特定域对象的细粒度权限控制。
通过这种方式,Spring Security 能够高效地处理大规模应用中的权限控制需求,同时避免在每个域对象上使用 GrantedAuthority 造成的内存和性能问题。

AuthenticationProvider身份验证提供者

可以将多个AuthenticationProviders实例注入ProviderManager。每个实例AuthenticationProvider执行特定类型的身份验证。例如,DaoAuthenticationProvider支持基于用户名/密码的身份验证,而JwtAuthenticationProvider支持对 JWT 令牌进行身份验证

请求凭证AuthenticationEntryPoin

AuthenticationEntryPoint用于发送向客户端请求凭据的 HTTP 响应。

有时,客户端会主动包含凭据(例如用户名和密码)来请求资源。在这些情况下,Spring Security 不需要提供向客户端请求凭据的 HTTP 响应,因为它们已经包含在内。

在其他情况下,客户端会向其无权访问的资源发出未经身份验证的请求。在这种情况下, 的实现AuthenticationEntryPoint用于向客户端请求凭据。该AuthenticationEntryPoint实现可能会重定向到登录页面、使用WWW-Authenticate标头进行响应或采取其他操作

流程

spring security

  1. 号当用户提交其凭证时, 会从AbstractAuthenticationProcessingFilter创建一个要进行身份验证的 。 创建的 类型取决于 的子类。 例如,会从中提交的用户名和密码创建一个。AuthenticationHttpServletRequestAuthenticationAbstractAuthenticationProcessingFilterUsernamePasswordAuthenticationFilterUsernamePasswordAuthenticationTokenHttpServletRequest

  2. 接下来,Authentication将传递到AuthenticationManager进行身份验证。

  3. 如果身份验证失败,则失败。

  • SecurityContextHolder已被清除。

  • RememberMeServices.loginFail被调用。如果未配置记住我,则此操作无效。请参阅rememberme包。

  • AuthenticationFailureHandler被调用。请参阅AuthenticationFailureHandler接口。

  1. 如果身份验证成功,则为Success。
  • SessionAuthenticationStrategy收到新登录通知。查看SessionAuthenticationStrategy界面。

  • Authentication在SecurityContextHolder上设置。稍后,如果您需要保存,以便在将来的请求中自动设置,则必须显式调用。请参阅类。SecurityContextSecurityContextRepository#saveContextSecurityContextHolderFilter

  • RememberMeServices.loginSuccess被调用。如果未配置记住我,则此操作无效。请参阅rememberme包。

  • ApplicationEventPublisher发布了一份InteractiveAuthenticationSuccessEvent。

  • AuthenticationSuccessHandler被调用。请参阅AuthenticationSuccessHandler接口。

java

maven转离线环境问题

2024-7-7 16:51:58

java

SSE流式响应 像chatGPT聊天一样

2024-10-11 10:20:04

0 条回复 A文章作者 M管理员
    暂无讨论,说说你的看法吧
个人中心
购物车
优惠劵
今日签到
有新私信 私信列表
搜索