Spring-Security

Spring Security 设置 Authentication Provider

1、概览 本文将带你了解如何在 Spring Security 中设置 Authentication Provider,相比于使用简单的 UserDetailsService 的标准方案,这样可以提供额外的灵活性。 2、Authentication Provider Spring Security 提供了多种执行身份认证的选项。这些选项遵循一个简单的契约;一个 AuthenticationProvider 处理一个身份认证请求,并返回一个带有完整凭证的认证对象。 最常见的标准实现是 DaoAuthenticationProvider,它从一个简单的 UserDetailsService(只读)中获取用户详细信息。这个 Service 只能通过用户名检索完整的用户实体,这在大多数情况下已足够。 更多的自定义场景仍需要访问完整的认证请求才能执行身份验证流程。例如,在对某些外部第三方服务进行身份验证时,身份认证请求中的 username 和 password 都是必要的。 对于这些更高级的场景,需要定义一个自定义的 Authentication Provider: @Component public class CustomAuthenticationProvider implements AuthenticationProvider { @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { String name = authentication.getName(); String password = authentication.getCredentials().toString(); if (shouldAuthenticateAgainstThirdPartySystem()) { // 使用凭证并对第三方系统进行身份认证 return new UsernamePasswordAuthenticationToken( name, password, new ArrayList<>()); } else { return null; } } @Override public boolean supports(Class<?

Spring Security 控制 Session

1、概览 本文将带你了解如何在 Spring Security 中配置 Session 超时、Session 并发以及其他高级的 Session 安全设置。 2、何时创建 Session? 可以精确控制 Session 的创建时间,以及 Spring Security 与 Session 的交互方式: always:如果 Session 不存在,则会创建一个 Session。 ifRequired:仅在需要时才创建 Session(默认值)。 never:框架不会自己创建 Session,但如果 Session 已经存在,则会使用该 Session。 stateless:Spring Security 不会创建或使用 Session。 <http create-session="ifRequired">...</http> Java 配置如下: @Bean public SecurityFilterChain filterChain(HttpSecurity http) throws Exception { http.sessionManagement() .sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED) return http.build(); } 注意,该配置只控制 Spring Security 的行为,而不是整个应用。如果指定 Spring Security 不创建 Session,它就不会创建 Session,但是应用可能会创建 Session! 默认情况下,Spring Security 会在需要时创建一个 Session,即 ifRequired。 对于无状态应用,never 选项将确保 Spring Security 本身不会创建任何 Session。但如果应用创建了 Session,Spring Security 就会使用它。

在 Spring Security 中获取当前用户

1、概览 本文介绍了如何在 Spring Security 中检索当前用户详细信息。 2、从 Bean 中获取用户 检索当前已通过身份认证用户(Principal)的最简单方式是调用 SecurityContextHolder 的静态方法: Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); String currentPrincipalName = authentication.getName(); 该代码需要改进的地方在于,在尝试访问之前,首先要检查是否存在已通过身份认证的用户: Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); if (!(authentication instanceof AnonymousAuthenticationToken)) { String currentUserName = authentication.getName(); return currentUserName; } 当然,这样的静态调用也有缺点,代码的可测试性降低了。 3、在 Controller 中获取用户 在 @Controller 中,可以直接将 Principal 定义为方法参数,这样框架就能正确地解析: @Controller public class GetUserWithPrincipalController { @RequestMapping(value = "/username", method = RequestMethod.GET) @ResponseBody public String currentUserName(Principal principal) { return principal.getName(); } } 或者,也可以使用 Authentication Token: @Controller public class GetUserWithAuthenticationController { @RequestMapping(value = "/username", method = RequestMethod.

Spring Security - 角色和权限

1、概览 本文将带你了解如何在 Spring Security 中正确地实现 角色(Role) 和 权限(Privilege)。 2、用户、角色和权限 有如下 3 个实体: User:代表用户 Role:代表用户在系统中的高级角色。每个角色都有一组低级权限。 Privilege:代表系统中较低级别的、细粒度的特权/权限。 User 如下: @Entity public class User { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String firstName; private String lastName; private String email; private String password; private boolean enabled; private boolean tokenExpired; @ManyToMany @JoinTable( name = "users_roles", joinColumns = @JoinColumn( name = "user_id", referencedColumnName = "id"), inverseJoinColumns = @JoinColumn( name = "role_id", referencedColumnName = "id")) private Collection<Role> roles; } 如上,用户包含角色和一些额外的细节,这些细节对于适当的注册机制来说是必要的。

在 Security Filter Chain 中自定义 Filter

1、概览 本文将带你了解如何在 Spring Security Filter Chain(过滤器链)中定义一个自定义过 Filter(过滤器)。 2、创建 Filter Spring Security 默认提供了许多 Filter,这些 Filter 在大多数情况下已经足够。 当然,有时也需要在链中创建一个新的 Filter 来实现新功能。 首先,可以实现 org.springframework.web.filter.GenericFilterBean。 GenericFilterBean 是一个简单的 javax.servlet.Filter 实现,它还实现了一系列的 Aware 接口,可以感知到 Spring 容器中的一些组件。 只需实现一个方法: public class CustomFilter extends GenericFilterBean { @Override public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { chain.doFilter(request, response); } } 3、在 Security Config 中配置 Filter 可以通过 XML 或 Java 配置把 Filter 配置到 Spring Security Filter Chain 中。

Spring Security - OAuth2 登录

1、概览 Spring Security 5 开始,引入了一个新的 OAuth2LoginConfigurer 类,可以用它来配置外部授权服务器(Authorization Server)。 本文主要带你了解 oauth2Login() 方法的一些可用配置选项。 2、Maven 依赖 在 Spring Boot 项目中,只需添加 spring-boot-starter-oauth2-client Starter 即可: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> <version>2.3.3.RELEASE</version> </dependency> 在非 Spring Boot 项目中,除了标准的 Spring 和 Spring Security 依赖外,还需要显式添加 spring-security-oauth2-client 和 spring-security-oauth2-jose 依赖: <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-client</artifactId> <version>5.3.4.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-jose</artifactId> <version>5.3.4.RELEASE</version> </dependency> 3、客户端设置 在 Spring Boot 项目中,只需为每个要配置的客户端添加几个标准属性即可。 接下来,我们要配置使用 Google 和 Facebook 作为 Authentication Provider 注册的客户端登录。 3.1、获取客户端凭证 要获取 Google OAuth2 身份认证的客户端凭证,请访问 Google API 控制台 的 “Credentials” 部分。

Spring Security 方法安全(Method Security)简介

1、概览 简而言之,Spring Security 支持方法级别的授权语义。可以通过限制哪些角色可以执行特定方法等方式来确保 Service 层的安全。 2、启用 Method Security 要使用 Spring Method Security,需要添加 spring-security-config 依赖: <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> </dependency> 可以在 Maven Central 上找到它的最新版本。 如果使用的是 Spring Boot,可以添加 spring-boot-starter-security 依赖,其中包括 spring-security-config: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> 同样,它的最新版本也可以在 Maven Central 中找到。 接下来,需要启用全局 Method Security: @Configuration @EnableGlobalMethodSecurity( prePostEnabled = true, securedEnabled = true, jsr250Enabled = true) public class MethodSecurityConfig extends GlobalMethodSecurityConfiguration { } prePostEnabled 属性可启用 Spring Security Pre/Post 注解。 securedEnabled 属性决定是否启用 @Secured 注解。 jsr250Enabled 属性允许使用 @RoleAllowed 注解。 3、应用 Method Security 3.

使用 Spring Security OAuth2 实现 SSO 单点登录

1、概览 本文将带你了解如何使用 Spring Security OAuth 和 Spring Boot 以及 Keycloak 作为授权服务器来实现单点登录(SSO)。 我们会使用 4 个不同的应用: 授权服务器 - 中央认证机制 资源服务器 - Foo 资源的提供者 两个客户端应用 - 使用 SSO 的应用 简单地说,当用户试图通过一个客户端应用访问资源时,他们会被重定到授权服务器进行身份认证。Keycloak 会对用户进行登录,在登录第一个应用后,如果使用同一浏览器访问第二个客户端应用,用户无需再次输入凭据。 使用 OAuth2 的授权码(Authorization Code)模式。 Spring Security 将此功能称为 OAuth 2.0 登录,而 Spring Security OAuth 将其称为 SSO。 2、授权服务器 以前,通过 Spring Security OAuth 可以将授权服务器设置为 Spring 应用。 不过,Spring Security OAuth 已被 Spring 弃用,现在可以使用 Keycloak 作为授权服务器。 因此,这次我们在 Spring Boot 应用中把授权服务器设置为嵌入式 Keycloak 服务器。 在 预配置 中,我们将定义两个客户端,即 ssoClient-1 和 ssoClient-2,分别对应每个客户端应用。

使用 Spring Security OAuth2 实现 SSO 单点登录(传统技术栈)

1、概览 本文将带你了解如何使用 Spring Security OAuth 和 Spring Boot 实现单点登录(SSO)。 我们会使用三个不同的应用: 授权服务器 - 中央认证机制 两个客户端应用:使用 SSO 的应用 简单来说,当用户试图访问客户端应用中受保护的页面时,他们会被重定向到过身份认证服务器进行身份验。使用 OAuth2 的 “授权码(Authorization Code)模式”。 注:本文使用的是 Spring OAuth 传统技术。如果你想查看新版 Spring Security 的版本,请参阅《使用 Spring Security OAuth2 实现 SSO 单点登录》。 2、客户端应用 从客户端应用开始。当然,使用 Spring Boot 构建。 2.1、Maven 依赖 在 pom.xml 中加入以下依赖: <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security.oauth.boot</groupId> <artifactId>spring-security-oauth2-autoconfigure</artifactId> <version>2.0.1.RELEASE</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-springsecurity4</artifactId> </dependency> 2.2、Security 配置 接下来是最重要的部分,即客户端应用的 Security 配置:

Spring Security 和 Apache Shiro

1、概览 在应用开发中,尤其是在企业级 Web 和移动应用领域,安全是一个首要问题。 本文将带你了解、比较两种流行的 Java 安全框架 - Apache Shiro 和 Spring Security。 2、背景 Apache Shiro 诞生于 2004 年,原名 JSecurity,2008 年被 Apache 基金会接受。迄今为止,它已发布了多个版本,最新版本为 1.13.0。 Spring Security 起源于 2003 年的 Acegi,在 2008 年首次公开发布时被纳入 Spring 框架。自诞生以来,它经历了多次迭代,目前的 GA 版本是 6.2.0。 这两种技术都提供身份认证和授权支持,以及加密和 Session 管理解决方案。此外,Spring Security 还提供了一流的保护,防范诸如 CSRF 和会话固定等攻击。 接下来,我们将通过使用 FreeMarker 的 Spring Boot 应用来演示如何使用这两种技术进行身份认证和授权。 3、配置 Apache Shiro 首先,来看看这两种框架的配置有何不同。 3.1、Maven 依赖 添加 shiro-spring-boot-web-starter 和 shiro-core 依赖: <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring-boot-web-starter</artifactId> <version>1.5.3</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.5.3</version> </dependency> 依赖的最新版本可在 Maven Central 上找到。