15. Servlet API integration(Servlet应用编程接口集成)
本节描述了Spring安全性是如何与Servlet API集成的。 servletapi-xml示例应用程序演示了这些方法的用法。
15.1 Servlet 2.5+ Integration(Servlet 2.5+集成)
15.1.1 HttpServletRequest.getRemoteUser()
HttpServletRequest.getRemoteUser() 将返回SecurityContextHolder.getContext().getAuthentication().getName()的结果。 这通常是当前的用户名。如果您想在应用程序中显示当前用户名,这将非常有用。此外,检查该值是否为空可用于指示用户是否已通过身份验证或匿名。了解用户是否经过身份验证对于确定是否应该显示某些用户界面元素非常有用(即,只有在用户经过身份验证时才应该显示注销链接)。
15.1.2 HttpServletRequest.getUserPrincipal()
HttpServletRequest.getUserPrincipal()将返回SecurityContextHolder.getContext().getAuthentication()的结果。这意味着当使用基于用户名和密码的身份验证时,它是一个身份验证,通常是UsernamePasswordAuthenticationToken 的一个实例。如果您需要关于您的用户的附加信息,这可能很有用。例如,您可能已经创建了一个自定义UserDetailsService,返回一个自定义的UserDetails包含您的用户的姓名。你可以用以下获得这些信息:
应该注意的是,在整个应用程序中执行如此多的逻辑通常是不好的做法。相反,应该对其进行集中,以减少Spring安全性和Servlet API的任何耦合。
15.1.3 HttpServletRequest.isUserInRole(String)
The HttpServletRequest.isUserInRole(String) 将确定 SecurityContextHolder.getContext().getAuthentication().getAuthorities() 包含一个 GrantedAuthority 角色传入的 isUserInRole(String)。 一般用户不应通过"ROLE_" 前缀到这个方法,因为它是自动添加的。例如,如果你想要确定当前用户有权力"ROLE_ADMIN",你可以使用以下:
booleanisAdmin = httpServletRequest.isUserInRole("ADMIN");
这可能有助于确定是否应该显示某些用户界面组件。例如,只有当当前用户是管理员时,您才可以显示管理员链接。
15.2 Servlet 3+ Integration
下一节描述了Spring安全集成的Servlet 3方法。
15.2.1 HttpServletRequest.authenticate(HttpServletResponse)
HttpServletRequest. authenticate(HttpServletResponse)方法可用于确保用户已通过身份验证。如果未通过身份验证,则配置的身份验证入口点将用于请求用户进行身份验证(即重定向至登录页面)。
15.2.2 HttpServletRequest.login(String,String)
The HttpServletRequest.login(String,String) 方法可用当前AuthenticationManager验证用户。例如,以下将尝试使用用户名“用户”和密码“密码”进行身份验证:
如果您尝试希望Spring Security处理失败的身份验证,则没有必要捕获ServletException。
15.2.3 HttpServletRequest.logout()
HttpServletRequest.logout()方法可以用来注销当前用户。
通常这意味着安全上下文持有者将被清除,HttpSession将被无效,任何“记住我”身份验证将被清除,等等。但是,根据您的Spring安全配置,配置的LogoutHandler实现会有所不同。需要注意的是,在调用了HttpServletRequest.logout()之后,你仍然负责写出回应。通常这包括重定向到欢迎页面。
15.2.4 AsyncContext.start(Runnable)
异步上下文启动AsyncContext.start.(Runnable)方法,确保您的凭证将被传播到新的线程。使用Spring安全的并发支持,Spring安全会覆盖AsyncContext.start(Runnable),以确保在处理线程时使用当前的安全上下文。
15.2.5 Async Servlet Support(异步Servlet支持)
如果您正在使用基于Java的配置,那么您已经准备好了。如果您使用的是XML配置,有一些必要的更新。第一步是确保您已经更新了web.xml,至少使用了3.0模式,如下所示:
接下来,您需要确保您的springSecurityFilterChain是为处理异步请求而设置的。
就这样!现在,Spring Security将确保您的SecurityContext也在异步请求上传播。
那么它是如何工作的呢?如果你真的不感兴趣,请跳过这一部分的剩余部分,否则请继续阅读。其中大部分都内置在Servlet规范中,但是Spring Security做了一些调整,以确保异步请求能够正常工作。在Spring Security 3.2之前,一旦提交了HttpServletResponse,就会自动保存来自SecurityContextHolder的SecurityContext。这可能会导致异步环境中的问题。例如,考虑以下情况:
问题是这个线程对于Spring Security是未知的,所以SecurityContext不会传播到它。这意味着当我们提交HttpServletResponse时,没有安全上下文。当Spring Security在提交HttpServletResponse时自动保存SecurityContext时,它将丢失我们的登录用户。自3.2版以来,Spring Security足够聪明,一旦调用了httperservletrequest . startasync(),就不再在提交HttpServletResponse时自动保存SecurityContext。
15.3 Servlet 3.1+ Integration
下一节描述了Spring安全集成的Servlet 3.1方法。
15.3.1 HttpServletRequest#changeSessionId()
The HttpServletRequest.changeSessionId() 是默认的方法防止 固定会话 损害Servlet 3.1或更高的版本。