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 就会使用它。
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.
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; } 如上,用户包含角色和一些额外的细节,这些细节对于适当的注册机制来说是必要的。
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 中。
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” 部分。
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.
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,分别对应每个客户端应用。
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 配置:
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 上找到。
1、概览 本文将带你了解如何使用 Spring Security 构建 OAuth 2.0 资源服务器(使用 JWT 和 Opaque Token,这两种由 Spring Security 支持的 Bearer Token)。
2、背景介绍 2.1、JWT 和 Opaque Token 是什么? JWT 或 JSON Web Token 是一种以广泛接受的 JSON 格式安全传输敏感信息的方式。其中包含的信息可能是关于用户的,也可能是关于 Token 本身的,例如其 expiry(有效期)和 issuer(签发者)。
Opaque Token 顾名思义,它所携带的信息是不透明的。Token 只是一个标识符,指向存储在授权服务器上的信息;它通过服务器端的自省(Introspection)进行验证。
2.2、资源服务器是什么? 在 OAuth 2.0 中,资源服务器是通过 OAuth Token 保护资源的应用。这些 Token 由授权服务器(通常是客户端应用)签发。资源服务器的工作是在向客户端提供资源之前验证 Token。
令牌的有效性由几个因素决定:
该令牌是否来自配置的授权服务器? 是否未过期? 该资源是否为预期受众(audience)提供服务? Token 是否具有访问所请求资源的必要权限? 来看一下 授权码模式 的顺序图,并观察所有相关的参与者:
正如在步骤 8 中看到的,当客户端应用调用资源服务器的 API 访问受保护的资源时,它首先会转到授权服务器,以验证请求的 Authorization: Bearer Header 信息中包含的 Token,然后响应客户端。
本文的重点是第 9 步。