Servlet 2.5+ 集成
本节介绍 Spring Security 如何与 Servlet 2.5 规范集成。
HttpServletRequest.getRemoteUser()
HttpServletRequest.getRemoteUser() 返回 的结果,通常是当前用户名。如果要在应用程序中显示当前用户名,这可能很有用。 此外,您可以检查此值是否为 null,以确定用户是否已通过身份验证或匿名。 了解用户是否经过身份验证可用于确定是否应显示某些 UI 元素(例如,仅当用户经过身份验证时才应显示的注销链接)。SecurityContextHolder.getContext().getAuthentication().getName()
HttpServletRequest.getUserPrincipal()
HttpServletRequest.getUserPrincipal() 返回 的结果。 这意味着它是一个 ,通常是使用基于用户名和密码的身份验证时的实例。 如果您需要有关用户的其他信息,这可能很有用。 例如,您可能已经创建了一个自定义项,该自定义项返回一个包含用户名字和姓氏的自定义项。 您可以通过以下方式获取此信息:SecurityContextHolder.getContext().getAuthentication()AuthenticationUsernamePasswordAuthenticationTokenUserDetailsServiceUserDetails
Java
Kotlin
Authentication auth = httpServletRequest.getUserPrincipal();// assume integrated custom UserDetails called MyCustomUserDetails// by default, typically instance of UserDetailsMyCustomUserDetails userDetails = (MyCustomUserDetails) auth.getPrincipal();String firstName = userDetails.getFirstName();String lastName = userDetails.getLastName();Copied!
应该注意的是,在整个应用程序中执行如此多的逻辑通常是不好的做法。 相反,应该将其集中起来,以减少Spring Security和Servlet API的任何耦合。
HttpServletRequest.isUserInRole(字符串)
HttpServletRequest.isUserInRole(String) 确定是否包含传递到 . 通常,用户不应将前缀传递给此方法,因为它是自动添加的。 例如,如果要确定当前用户是否具有“ROLE_ADMIN”权限,则可以使用以下命令:SecurityContextHolder.getContext().getAuthentication().getAuthorities()GrantedAuthorityisUserInRole(String)ROLE_
Java
Kotlin
boolean isAdmin = httpServletRequest.isUserInRole("ADMIN");Copied!
这对于确定是否应显示某些 UI 组件可能很有用。 例如,仅当当前用户是管理员时,才可以显示管理员链接。
应该注意的是,在整个应用程序中执行如此多的逻辑通常是不好的做法。 相反,应该将其集中起来,以减少Spring Security和Servlet API的任何耦合。
Servlet 3+ 集成
以下部分介绍了 Spring Security 与之集成的 Servlet 3 方法。
HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse)
可以使用 HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse) 方法确保用户已通过身份验证。 如果未进行身份验证,则配置用于请求用户进行身份验证(重定向到登录页面)。AuthenticationEntryPoint
HttpServletRequest.login(字符串,字符串)
可以使用 HttpServletRequest.login(String,String) 方法使用当前 . 例如,以下人员将尝试使用用户名和密码进行身份验证:AuthenticationManageruserpassword
Java
Kotlin
try {httpServletRequest.login("user","password");} catch(ServletException ex) {// fail to authenticate}Copied!
如果您希望 Spring Security 处理失败的身份验证尝试,则无需捕获。ServletException
HttpServletRequest.logout()
可以使用 HttpServletRequest.logout() 方法注销当前用户。
通常,这意味着清除、无效、清理任何“记住我”身份验证,等等。 但是,配置的实现会有所不同,具体取决于您的 Spring Security 配置。 请注意,在调用后,您仍然负责写出响应。 通常,这将涉及重定向到欢迎页面。SecurityContextHolderHttpSessionLogoutHandlerHttpServletRequest.logout()
AsyncContext.start(可运行)
AsyncContext.start(Runnable) 方法可确保将凭据传播到新的 . 通过使用 Spring Security 的并发支持,Spring Security 会覆盖以确保在处理 Runnable 时使用当前。 以下示例输出当前用户的身份验证:ThreadAsyncContext.start(Runnable)SecurityContext
Java
Kotlin
final AsyncContext async = httpServletRequest.startAsync();async.start(new Runnable() {public void run() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();try {final HttpServletResponse asyncResponse = (HttpServletResponse) async.getResponse();asyncResponse.setStatus(HttpServletResponse.SC_OK);asyncResponse.getWriter().write(String.valueOf(authentication));async.complete();} catch(Exception ex) {throw new RuntimeException(ex);}}});Copied!异步 Servlet 支持
如果您使用基于 Java 的配置,那么您就可以开始了。 如果使用 XML 配置,则需要进行一些更新。 第一步是确保已更新文件以至少使用 3.0 架构:web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"version="3.0"></web-app>Copied!
接下来,您需要确保已设置为处理异步请求:springSecurityFilterChain
<filter><filter-name>springSecurityFilterChain</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class><async-supported>true</async-supported></filter><filter-mapping><filter-name>springSecurityFilterChain</filter-name><url-pattern>/*</url-pattern><dispatcher>REQUEST</dispatcher><dispatcher>ASYNC</dispatcher></filter-mapping>Copied!
现在,Spring Security 也确保在异步请求上传播您的内容。SecurityContext
那么它是如何工作的呢?如果您真的不感兴趣,请随时跳过本节的其余部分 其中大部分都内置在 Servlet 规范中,但 Spring Security 做了一些调整,以确保异步请求正常工作。 在 Spring Security 3.2 之前,from 会在提交后立即自动保存。 这可能会导致异步环境中出现问题。 请看以下示例:SecurityContextSecurityContextHolderHttpServletResponse
Java
Kotlin
httpServletRequest.startAsync();new Thread("AsyncThread") {@Overridepublic void run() {try {// Do workTimeUnit.SECONDS.sleep(1);// Write to and commit the httpServletResponsehttpServletResponse.getOutputStream().flush();} catch (Exception ex) {ex.printStackTrace();}}}.start();Copied!
问题是Spring Security不知道这一点,因此不会传播到它。 这意味着,当我们提交 时,没有 . 当 Spring Security 自动保存 时提交 ,它将丢失登录用户。ThreadSecurityContextHttpServletResponseSecurityContextSecurityContextHttpServletResponse
从 3.2 版开始,Spring Security 足够智能,不再在调用时立即自动保存提交。SecurityContextHttpServletResponseHttpServletRequest.startAsync()
如果您希望 Spring Security 处理失败的身份验证尝试,则无需捕获。ServletException
Servlet 3.1+ 集成
以下部分介绍了 Spring Security 集成的 Servlet 3.1 方法。
HttpServletRequest#changeSessionId()
HttpServletRequest.changeSessionId() 是 Servlet 3.1 及更高版本中用于防止会话固定攻击的默认方法。
来源:spring-doc.cadn.net.cn/spring-security/6.3.1/servlet_integrations_servlet-api.html
本节介绍 Spring Security 如何与 Servlet 2.5 规范集成。
HttpServletRequest.getRemoteUser()
HttpServletRequest.getRemoteUser() 返回 的结果,通常是当前用户名。如果要在应用程序中显示当前用户名,这可能很有用。 此外,您可以检查此值是否为 null,以确定用户是否已通过身份验证或匿名。 了解用户是否经过身份验证可用于确定是否应显示某些 UI 元素(例如,仅当用户经过身份验证时才应显示的注销链接)。SecurityContextHolder.getContext().getAuthentication().getName()
HttpServletRequest.getUserPrincipal()
HttpServletRequest.getUserPrincipal() 返回 的结果。 这意味着它是一个 ,通常是使用基于用户名和密码的身份验证时的实例。 如果您需要有关用户的其他信息,这可能很有用。 例如,您可能已经创建了一个自定义项,该自定义项返回一个包含用户名字和姓氏的自定义项。 您可以通过以下方式获取此信息:SecurityContextHolder.getContext().getAuthentication()AuthenticationUsernamePasswordAuthenticationTokenUserDetailsServiceUserDetails
Java
Kotlin
Authentication auth = httpServletRequest.getUserPrincipal();// assume integrated custom UserDetails called MyCustomUserDetails// by default, typically instance of UserDetailsMyCustomUserDetails userDetails = (MyCustomUserDetails) auth.getPrincipal();String firstName = userDetails.getFirstName();String lastName = userDetails.getLastName();Copied!
应该注意的是,在整个应用程序中执行如此多的逻辑通常是不好的做法。 相反,应该将其集中起来,以减少Spring Security和Servlet API的任何耦合。
HttpServletRequest.isUserInRole(字符串)
HttpServletRequest.isUserInRole(String) 确定是否包含传递到 . 通常,用户不应将前缀传递给此方法,因为它是自动添加的。 例如,如果要确定当前用户是否具有“ROLE_ADMIN”权限,则可以使用以下命令:SecurityContextHolder.getContext().getAuthentication().getAuthorities()GrantedAuthorityisUserInRole(String)ROLE_
Java
Kotlin
boolean isAdmin = httpServletRequest.isUserInRole("ADMIN");Copied!
这对于确定是否应显示某些 UI 组件可能很有用。 例如,仅当当前用户是管理员时,才可以显示管理员链接。
应该注意的是,在整个应用程序中执行如此多的逻辑通常是不好的做法。 相反,应该将其集中起来,以减少Spring Security和Servlet API的任何耦合。
Servlet 3+ 集成
以下部分介绍了 Spring Security 与之集成的 Servlet 3 方法。
HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse)
可以使用 HttpServletRequest.authenticate(HttpServletRequest,HttpServletResponse) 方法确保用户已通过身份验证。 如果未进行身份验证,则配置用于请求用户进行身份验证(重定向到登录页面)。AuthenticationEntryPoint
HttpServletRequest.login(字符串,字符串)
可以使用 HttpServletRequest.login(String,String) 方法使用当前 . 例如,以下人员将尝试使用用户名和密码进行身份验证:AuthenticationManageruserpassword
Java
Kotlin
try {httpServletRequest.login("user","password");} catch(ServletException ex) {// fail to authenticate}Copied!
如果您希望 Spring Security 处理失败的身份验证尝试,则无需捕获。ServletException
HttpServletRequest.logout()
可以使用 HttpServletRequest.logout() 方法注销当前用户。
通常,这意味着清除、无效、清理任何“记住我”身份验证,等等。 但是,配置的实现会有所不同,具体取决于您的 Spring Security 配置。 请注意,在调用后,您仍然负责写出响应。 通常,这将涉及重定向到欢迎页面。SecurityContextHolderHttpSessionLogoutHandlerHttpServletRequest.logout()
AsyncContext.start(可运行)
AsyncContext.start(Runnable) 方法可确保将凭据传播到新的 . 通过使用 Spring Security 的并发支持,Spring Security 会覆盖以确保在处理 Runnable 时使用当前。 以下示例输出当前用户的身份验证:ThreadAsyncContext.start(Runnable)SecurityContext
Java
Kotlin
final AsyncContext async = httpServletRequest.startAsync();async.start(new Runnable() {public void run() {Authentication authentication = SecurityContextHolder.getContext().getAuthentication();try {final HttpServletResponse asyncResponse = (HttpServletResponse) async.getResponse();asyncResponse.setStatus(HttpServletResponse.SC_OK);asyncResponse.getWriter().write(String.valueOf(authentication));async.complete();} catch(Exception ex) {throw new RuntimeException(ex);}}});Copied!异步 Servlet 支持
如果您使用基于 Java 的配置,那么您就可以开始了。 如果使用 XML 配置,则需要进行一些更新。 第一步是确保已更新文件以至少使用 3.0 架构:web.xml
<web-app xmlns="http://java.sun.com/xml/ns/javaee"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://java.sun.com/xml/ns/javaee https://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"version="3.0"></web-app>Copied!
接下来,您需要确保已设置为处理异步请求:springSecurityFilterChain
<filter><filter-name>springSecurityFilterChain</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class><async-supported>true</async-supported></filter><filter-mapping><filter-name>springSecurityFilterChain</filter-name><url-pattern>/*</url-pattern><dispatcher>REQUEST</dispatcher><dispatcher>ASYNC</dispatcher></filter-mapping>Copied!
现在,Spring Security 也确保在异步请求上传播您的内容。SecurityContext
那么它是如何工作的呢?如果您真的不感兴趣,请随时跳过本节的其余部分 其中大部分都内置在 Servlet 规范中,但 Spring Security 做了一些调整,以确保异步请求正常工作。 在 Spring Security 3.2 之前,from 会在提交后立即自动保存。 这可能会导致异步环境中出现问题。 请看以下示例:SecurityContextSecurityContextHolderHttpServletResponse
Java
Kotlin
httpServletRequest.startAsync();new Thread("AsyncThread") {@Overridepublic void run() {try {// Do workTimeUnit.SECONDS.sleep(1);// Write to and commit the httpServletResponsehttpServletResponse.getOutputStream().flush();} catch (Exception ex) {ex.printStackTrace();}}}.start();Copied!
问题是Spring Security不知道这一点,因此不会传播到它。 这意味着,当我们提交 时,没有 . 当 Spring Security 自动保存 时提交 ,它将丢失登录用户。ThreadSecurityContextHttpServletResponseSecurityContextSecurityContextHttpServletResponse
从 3.2 版开始,Spring Security 足够智能,不再在调用时立即自动保存提交。SecurityContextHttpServletResponseHttpServletRequest.startAsync()
如果您希望 Spring Security 处理失败的身份验证尝试,则无需捕获。ServletException
Servlet 3.1+ 集成
以下部分介绍了 Spring Security 集成的 Servlet 3.1 方法。
HttpServletRequest#changeSessionId()
HttpServletRequest.changeSessionId() 是 Servlet 3.1 及更高版本中用于防止会话固定攻击的默认方法。
来源:spring-doc.cadn.net.cn/spring-security/6.3.1/servlet_integrations_servlet-api.html