248.f7b4f364.js 13.6 KB
Newer Older
茶陵後's avatar
茶陵後 已提交
1
(window.webpackJsonp=window.webpackJsonp||[]).push([[248],{674:function(e,t,a){"use strict";a.r(t);var i=a(56),n=Object(i.a)({},(function(){var e=this,t=e.$createElement,a=e._self._c||t;return a("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[a("h1",{attrs:{id:"pre-authentication-scenarios"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#pre-authentication-scenarios"}},[e._v("#")]),e._v(" Pre-Authentication Scenarios")]),e._v(" "),a("p",[e._v("Examples include X.509, Siteminder and authentication by the Java EE container in which the application is running.\nWhen using pre-authentication, Spring Security has to")]),e._v(" "),a("ul",[a("li",[a("p",[e._v("Identify the user making the request.")])]),e._v(" "),a("li",[a("p",[e._v("Obtain the authorities for the user.")])])]),e._v(" "),a("p",[e._v("The details will depend on the external authentication mechanism.\nA user might be identified by their certificate information in the case of X.509, or by an HTTP request header in the case of Siteminder.\nIf relying on container authentication, the user will be identified by calling the "),a("code",[e._v("getUserPrincipal()")]),e._v(" method on the incoming HTTP request.\nIn some cases, the external mechanism may supply role/authority information for the user but in others the authorities must be obtained from a separate source, such as a "),a("code",[e._v("UserDetailsService")]),e._v(".")]),e._v(" "),a("h2",{attrs:{id:"pre-authentication-framework-classes"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#pre-authentication-framework-classes"}},[e._v("#")]),e._v(" Pre-Authentication Framework Classes")]),e._v(" "),a("p",[e._v("Because most pre-authentication mechanisms follow the same pattern, Spring Security has a set of classes which provide an internal framework for implementing pre-authenticated authentication providers.\nThis removes duplication and allows new implementations to be added in a structured fashion, without having to write everything from scratch.\nYou don’t need to know about these classes if you want to use something like "),a("RouterLink",{attrs:{to:"/en/spring-security/x509.html#servlet-x509"}},[e._v("X.509 authentication")]),e._v(", as it already has a namespace configuration option which is simpler to use and get started with.\nIf you need to use explicit bean configuration or are planning on writing your own implementation then an understanding of how the provided implementations work will be useful.\nYou will find classes under the "),a("code",[e._v("org.springframework.security.web.authentication.preauth")]),e._v(".\nWe just provide an outline here so you should consult the Javadoc and source where appropriate.")],1),e._v(" "),a("h3",{attrs:{id:"abstractpreauthenticatedprocessingfilter"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#abstractpreauthenticatedprocessingfilter"}},[e._v("#")]),e._v(" AbstractPreAuthenticatedProcessingFilter")]),e._v(" "),a("p",[e._v("This class will check the current contents of the security context and, if empty, it will attempt to extract user information from the HTTP request and submit it to the "),a("code",[e._v("AuthenticationManager")]),e._v(".\nSubclasses override the following methods to obtain this information:")]),e._v(" "),a("p",[e._v("Example 1. Override AbstractPreAuthenticatedProcessingFilter")]),e._v(" "),a("p",[e._v("Java")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("protected abstract Object getPreAuthenticatedPrincipal(HttpServletRequest request);\n\nprotected abstract Object getPreAuthenticatedCredentials(HttpServletRequest request);\n")])])]),a("p",[e._v("Kotlin")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("protected abstract fun getPreAuthenticatedPrincipal(request: HttpServletRequest): Any?\n\nprotected abstract fun getPreAuthenticatedCredentials(request: HttpServletRequest): Any?\n")])])]),a("p",[e._v("After calling these, the filter will create a "),a("code",[e._v("PreAuthenticatedAuthenticationToken")]),e._v(' containing the returned data and submit it for authentication.\nBy "authentication" here, we really just mean further processing to perhaps load the user’s authorities, but the standard Spring Security authentication architecture is followed.')]),e._v(" "),a("p",[e._v("Like other Spring Security authentication filters, the pre-authentication filter has an "),a("code",[e._v("authenticationDetailsSource")]),e._v(" property which by default will create a "),a("code",[e._v("WebAuthenticationDetails")]),e._v(" object to store additional information such as the session-identifier and originating IP address in the "),a("code",[e._v("details")]),e._v(" property of the "),a("code",[e._v("Authentication")]),e._v(" object.\nIn cases where user role information can be obtained from the pre-authentication mechanism, the data is also stored in this property, with the details implementing the "),a("code",[e._v("GrantedAuthoritiesContainer")]),e._v(" interface.\nThis enables the authentication provider to read the authorities which were externally allocated to the user.\nWe’ll look at a concrete example next.")]),e._v(" "),a("h4",{attrs:{id:"j2eebasedpreauthenticatedwebauthenticationdetailssource"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#j2eebasedpreauthenticatedwebauthenticationdetailssource"}},[e._v("#")]),e._v(" J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource")]),e._v(" "),a("p",[e._v("If the filter is configured with an "),a("code",[e._v("authenticationDetailsSource")]),e._v(" which is an instance of this class, the authority information is obtained by calling the "),a("code",[e._v("isUserInRole(String role)")]),e._v(' method for each of a pre-determined set of "mappable roles".\nThe class gets these from a configured '),a("code",[e._v("MappableAttributesRetriever")]),e._v(".\nPossible implementations include hard-coding a list in the application context and reading the role information from the "),a("code",[e._v("<security-role>")]),e._v(" information in a "),a("code",[e._v("web.xml")]),e._v(" file.\nThe pre-authentication sample application uses the latter approach.")]),e._v(" "),a("p",[e._v("There is an additional stage where the roles (or attributes) are mapped to Spring Security "),a("code",[e._v("GrantedAuthority")]),e._v(" objects using a configured "),a("code",[e._v("Attributes2GrantedAuthoritiesMapper")]),e._v(".\nThe default will just add the usual "),a("code",[e._v("ROLE_")]),e._v(" prefix to the names, but it gives you full control over the behaviour.")]),e._v(" "),a("h3",{attrs:{id:"preauthenticatedauthenticationprovider"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#preauthenticatedauthenticationprovider"}},[e._v("#")]),e._v(" PreAuthenticatedAuthenticationProvider")]),e._v(" "),a("p",[e._v("The pre-authenticated provider has little more to do than load the "),a("code",[e._v("UserDetails")]),e._v(" object for the user.\nIt does this by delegating to an "),a("code",[e._v("AuthenticationUserDetailsService")]),e._v(".\nThe latter is similar to the standard "),a("code",[e._v("UserDetailsService")]),e._v(" but takes an "),a("code",[e._v("Authentication")]),e._v(" object rather than just user name:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v("public interface AuthenticationUserDetailsService {\n\tUserDetails loadUserDetails(Authentication token) throws UsernameNotFoundException;\n}\n")])])]),a("p",[e._v("This interface may have also other uses but with pre-authentication it allows access to the authorities which were packaged in the "),a("code",[e._v("Authentication")]),e._v(" object, as we saw in the previous section.\nThe "),a("code",[e._v("PreAuthenticatedGrantedAuthoritiesUserDetailsService")]),e._v(" class does this.\nAlternatively, it may delegate to a standard "),a("code",[e._v("UserDetailsService")]),e._v(" via the "),a("code",[e._v("UserDetailsByNameServiceWrapper")]),e._v(" implementation.")]),e._v(" "),a("h3",{attrs:{id:"http403forbiddenentrypoint"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#http403forbiddenentrypoint"}},[e._v("#")]),e._v(" Http403ForbiddenEntryPoint")]),e._v(" "),a("p",[e._v("The "),a("RouterLink",{attrs:{to:"/en/spring-security/architecture.html#servlet-authentication-authenticationentrypoint"}},[a("code",[e._v("AuthenticationEntryPoint")])]),e._v(" is responsible for kick-starting the authentication process for an unauthenticated user (when they try to access a protected resource), but in the pre-authenticated case this doesn’t apply.\nYou would only configure the "),a("code",[e._v("ExceptionTranslationFilter")]),e._v(" with an instance of this class if you aren’t using pre-authentication in combination with other authentication mechanisms.\nIt will be called if the user is rejected by the "),a("code",[e._v("AbstractPreAuthenticatedProcessingFilter")]),e._v(" resulting in a null authentication.\nIt always returns a "),a("code",[e._v("403")]),e._v("-forbidden response code if called.")],1),e._v(" "),a("h2",{attrs:{id:"concrete-implementations"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#concrete-implementations"}},[e._v("#")]),e._v(" Concrete Implementations")]),e._v(" "),a("p",[e._v("X.509 authentication is covered in its "),a("RouterLink",{attrs:{to:"/en/spring-security/x509.html#servlet-x509"}},[e._v("own chapter")]),e._v(".\nHere we’ll look at some classes which provide support for other pre-authenticated scenarios.")],1),e._v(" "),a("h3",{attrs:{id:""}},[a("a",{staticClass:"header-anchor",attrs:{href:"#"}},[e._v("#")])]),e._v(" "),a("p",[e._v("An external authentication system may supply information to the application by setting specific headers on the HTTP request.\nA well-known example of this is Siteminder, which passes the username in a header called "),a("code",[e._v("SM_USER")]),e._v(".\nThis mechanism is supported by the class "),a("code",[e._v("RequestHeaderAuthenticationFilter")]),e._v(" which simply extracts the username from the header.\nIt defaults to using the name "),a("code",[e._v("SM_USER")]),e._v(" as the header name.\nSee the Javadoc for more details.")]),e._v(" "),a("table",[a("thead",[a("tr",[a("th"),e._v(" "),a("th",[e._v("Note that when using a system like this, the framework performs no authentication checks at all and it is "),a("em",[e._v("extremely")]),e._v(" important that the external system is configured properly and protects all access to the application."),a("br"),e._v("If an attacker is able to forge the headers in their original request without this being detected then they could potentially choose any username they wished.")])])]),e._v(" "),a("tbody")]),e._v(" "),a("h4",{attrs:{id:"siteminder-example-configuration"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#siteminder-example-configuration"}},[e._v("#")]),e._v(" Siteminder Example Configuration")]),e._v(" "),a("p",[e._v("A typical configuration using this filter would look like this:")]),e._v(" "),a("div",{staticClass:"language- extra-class"},[a("pre",{pre:!0,attrs:{class:"language-text"}},[a("code",[e._v('<security:http>\n\x3c!-- Additional http configuration omitted --\x3e\n<security:custom-filter position="PRE_AUTH_FILTER" ref="siteminderFilter" />\n</security:http>\n\n<bean id="siteminderFilter" class="org.springframework.security.web.authentication.preauth.RequestHeaderAuthenticationFilter">\n<property name="principalRequestHeader" value="SM_USER"/>\n<property name="authenticationManager" ref="authenticationManager" />\n</bean>\n\n<bean id="preauthAuthProvider" class="org.springframework.security.web.authentication.preauth.PreAuthenticatedAuthenticationProvider">\n<property name="preAuthenticatedUserDetailsService">\n\t<bean id="userDetailsServiceWrapper"\n\t\tclass="org.springframework.security.core.userdetails.UserDetailsByNameServiceWrapper">\n\t<property name="userDetailsService" ref="userDetailsService"/>\n\t</bean>\n</property>\n</bean>\n\n<security:authentication-manager alias="authenticationManager">\n<security:authentication-provider ref="preauthAuthProvider" />\n</security:authentication-manager>\n')])])]),a("p",[e._v("We’ve assumed here that the "),a("RouterLink",{attrs:{to:"/en/configuration/xml-namespace.html#ns-config"}},[e._v("security namespace")]),e._v(" is being used for configuration.\nIt’s also assumed that you have added a "),a("code",[e._v("UserDetailsService")]),e._v(' (called "userDetailsService") to your configuration to load the user’s roles.')],1),e._v(" "),a("h3",{attrs:{id:"java-ee-container-authentication"}},[a("a",{staticClass:"header-anchor",attrs:{href:"#java-ee-container-authentication"}},[e._v("#")]),e._v(" Java EE Container Authentication")]),e._v(" "),a("p",[e._v("The class "),a("code",[e._v("J2eePreAuthenticatedProcessingFilter")]),e._v(" will extract the username from the "),a("code",[e._v("userPrincipal")]),e._v(" property of the "),a("code",[e._v("HttpServletRequest")]),e._v(".\nUse of this filter would usually be combined with the use of Java EE roles as described above in "),a("a",{attrs:{href:"#j2ee-preauth-details"}},[e._v("J2eeBasedPreAuthenticatedWebAuthenticationDetailsSource")]),e._v(".")]),e._v(" "),a("p",[e._v("There is a "),a("a",{attrs:{href:"https://github.com/spring-projects/spring-security/tree/5.4.x/samples/xml/preauth",target:"_blank",rel:"noopener noreferrer"}},[e._v("sample application"),a("OutboundLink")],1),e._v(" in the samples project which uses this approach, so get hold of the code from GitHub and have a look at the application context file if you are interested.")]),e._v(" "),a("p",[a("RouterLink",{attrs:{to:"/en/spring-security/anonymous.html"}},[e._v("Anonymous")]),a("RouterLink",{attrs:{to:"/en/spring-security/jaas.html"}},[e._v("JAAS")])],1)])}),[],!1,null,null,null);t.default=n.exports}}]);