(window.webpackJsonp=window.webpackJsonp||[]).push([[228],{652:function(e,t,n){"use strict";n.r(t);var a=n(56),o=Object(a.a)({},(function(){var e=this,t=e.$createElement,n=e._self._c||t;return n("ContentSlotsDistributor",{attrs:{"slot-key":e.$parent.slotKey}},[n("h1",{attrs:{id:"anonymous-authentication"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#anonymous-authentication"}},[e._v("#")]),e._v(" Anonymous Authentication")]),e._v(" "),n("h2",{attrs:{id:"overview"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#overview"}},[e._v("#")]),e._v(" Overview")]),e._v(" "),n("p",[e._v('It’s generally considered good security practice to adopt a "deny-by-default" where you explicitly specify what is allowed and disallow everything else.\nDefining what is accessible to unauthenticated users is a similar situation, particularly for web applications.\nMany sites require that users must be authenticated for anything other than a few URLs (for example the home and login pages).\nIn this case it is easiest to define access configuration attributes for these specific URLs rather than have for every secured resource.\nPut differently, sometimes it is nice to say '),n("code",[e._v("ROLE_SOMETHING")]),e._v(" is required by default and only allow certain exceptions to this rule, such as for login, logout and home pages of an application.\nYou could also omit these pages from the filter chain entirely, thus bypassing the access control checks, but this may be undesirable for other reasons, particularly if the pages behave differently for authenticated users.")]),e._v(" "),n("p",[e._v('This is what we mean by anonymous authentication.\nNote that there is no real conceptual difference between a user who is "anonymously authenticated" and an unauthenticated user.\nSpring Security’s anonymous authentication just gives you a more convenient way to configure your access-control attributes.\nCalls to servlet API such as '),n("code",[e._v("getCallerPrincipal")]),e._v(", for example, will still return null even though there is actually an anonymous authentication object in the "),n("code",[e._v("SecurityContextHolder")]),e._v(".")]),e._v(" "),n("p",[e._v("There are other situations where anonymous authentication is useful, such as when an auditing interceptor queries the "),n("code",[e._v("SecurityContextHolder")]),e._v(" to identify which principal was responsible for a given operation.\nClasses can be authored more robustly if they know the "),n("code",[e._v("SecurityContextHolder")]),e._v(" always contains an "),n("code",[e._v("Authentication")]),e._v(" object, and never "),n("code",[e._v("null")]),e._v(".")]),e._v(" "),n("h2",{attrs:{id:"configuration"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#configuration"}},[e._v("#")]),e._v(" Configuration")]),e._v(" "),n("p",[e._v("Anonymous authentication support is provided automatically when using the HTTP configuration Spring Security 3.0 and can be customized (or disabled) using the "),n("code",[e._v("")]),e._v(" element.\nYou don’t need to configure the beans described here unless you are using traditional bean configuration.")]),e._v(" "),n("p",[e._v("Three classes that together provide the anonymous authentication feature."),n("code",[e._v("AnonymousAuthenticationToken")]),e._v(" is an implementation of "),n("code",[e._v("Authentication")]),e._v(", and stores the "),n("code",[e._v("GrantedAuthority")]),e._v("s which apply to the anonymous principal.\nThere is a corresponding "),n("code",[e._v("AnonymousAuthenticationProvider")]),e._v(", which is chained into the "),n("code",[e._v("ProviderManager")]),e._v(" so that "),n("code",[e._v("AnonymousAuthenticationToken")]),e._v("s are accepted.\nFinally, there is an "),n("code",[e._v("AnonymousAuthenticationFilter")]),e._v(", which is chained after the normal authentication mechanisms and automatically adds an "),n("code",[e._v("AnonymousAuthenticationToken")]),e._v(" to the "),n("code",[e._v("SecurityContextHolder")]),e._v(" if there is no existing "),n("code",[e._v("Authentication")]),e._v(" held there.\nThe definition of the filter and authentication provider appears as follows:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('\n\n\n\n\n\n\n\n')])])]),n("p",[e._v("The "),n("code",[e._v("key")]),e._v(" is shared between the filter and authentication provider, so that tokens created by the former are accepted by the latter "),n("sup",{staticClass:"footnote"},[e._v("["),n("a",{staticClass:"footnote",attrs:{id:"_footnoteref_1",href:"#_footnotedef_1",title:"View footnote."}},[e._v("1")]),e._v("]")]),e._v(".\nThe "),n("code",[e._v("userAttribute")]),e._v(" is expressed in the form of "),n("code",[e._v("usernameInTheAuthenticationToken,grantedAuthority[,grantedAuthority]")]),e._v(".\nThis is the same syntax as used after the equals sign for the "),n("code",[e._v("userMap")]),e._v(" property of "),n("code",[e._v("InMemoryDaoImpl")]),e._v(".")]),e._v(" "),n("p",[e._v("As explained earlier, the benefit of anonymous authentication is that all URI patterns can have security applied to them.\nFor example:")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v("\n\n\n\n\t\n\t\n\t\n\t\n\t\n\t\n\t\" +\n\n\n")])])]),n("h2",{attrs:{id:"authenticationtrustresolver"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#authenticationtrustresolver"}},[e._v("#")]),e._v(" AuthenticationTrustResolver")]),e._v(" "),n("p",[e._v("Rounding out the anonymous authentication discussion is the "),n("code",[e._v("AuthenticationTrustResolver")]),e._v(" interface, with its corresponding "),n("code",[e._v("AuthenticationTrustResolverImpl")]),e._v(" implementation.\nThis interface provides an "),n("code",[e._v("isAnonymous(Authentication)")]),e._v(" method, which allows interested classes to take into account this special type of authentication status.\nThe "),n("code",[e._v("ExceptionTranslationFilter")]),e._v(" uses this interface in processing "),n("code",[e._v("AccessDeniedException")]),e._v("s.\nIf an "),n("code",[e._v("AccessDeniedException")]),e._v(" is thrown, and the authentication is of an anonymous type, instead of throwing a 403 (forbidden) response, the filter will instead commence the "),n("code",[e._v("AuthenticationEntryPoint")]),e._v(' so the principal can authenticate properly.\nThis is a necessary distinction, otherwise principals would always be deemed "authenticated" and never be given an opportunity to login via form, basic, digest or some other normal authentication mechanism.')]),e._v(" "),n("p",[e._v("You will often see the "),n("code",[e._v("ROLE_ANONYMOUS")]),e._v(" attribute in the above interceptor configuration replaced with "),n("code",[e._v("IS_AUTHENTICATED_ANONYMOUSLY")]),e._v(", which is effectively the same thing when defining access controls.\nThis is an example of the use of the "),n("code",[e._v("AuthenticatedVoter")]),e._v(" which we will see in the "),n("RouterLink",{attrs:{to:"/en/authorization/architecture.html#authz-authenticated-voter"}},[e._v("authorization chapter")]),e._v(".\nIt uses an "),n("code",[e._v("AuthenticationTrustResolver")]),e._v(" to process this particular configuration attribute and grant access to anonymous users.\nThe "),n("code",[e._v("AuthenticatedVoter")]),e._v(" approach is more powerful, since it allows you to differentiate between anonymous, remember-me and fully-authenticated users.\nIf you don’t need this functionality though, then you can stick with "),n("code",[e._v("ROLE_ANONYMOUS")]),e._v(", which will be processed by Spring Security’s standard "),n("code",[e._v("RoleVoter")]),e._v(".")],1),e._v(" "),n("h2",{attrs:{id:"getting-anonymous-authentications-with-spring-mvc"}},[n("a",{staticClass:"header-anchor",attrs:{href:"#getting-anonymous-authentications-with-spring-mvc"}},[e._v("#")]),e._v(" Getting Anonymous Authentications with Spring MVC")]),e._v(" "),n("p",[n("a",{attrs:{href:"https://docs.spring.io/spring-framework/docs/current/reference/html/web.html#mvc-ann-arguments",target:"_blank",rel:"noopener noreferrer"}},[e._v("Spring MVC resolves parameters of type "),n("code",[e._v("Principal")]),n("OutboundLink")],1),e._v(" using its own argument resolver.")]),e._v(" "),n("p",[e._v("This means that a construct like this one:")]),e._v(" "),n("p",[e._v("Java")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@GetMapping("/")\npublic String method(Authentication authentication) {\n\tif (authentication instanceof AnonymousAuthenticationToken) {\n\t\treturn "anonymous";\n\t} else {\n\t\treturn "not anonymous";\n\t}\n}\n')])])]),n("p",[e._v("Kotlin")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@GetMapping("/")\nfun method(authentication: Authentication?): String {\n return if (authentication is AnonymousAuthenticationToken) {\n "anonymous"\n } else {\n "not anonymous"\n }\n}\n')])])]),n("p",[e._v('will always return "not anonymous", even for anonymous requests.\nThe reason is that Spring MVC resolves the parameter using '),n("code",[e._v("HttpServletRequest#getPrincipal")]),e._v(", which is "),n("code",[e._v("null")]),e._v(" when the request is anonymous.")]),e._v(" "),n("p",[e._v("If you’d like to obtain the "),n("code",[e._v("Authentication")]),e._v(" in anonymous requests, use "),n("code",[e._v("@CurrentSecurityContext")]),e._v(" instead:")]),e._v(" "),n("p",[e._v("Example 1. Use CurrentSecurityContext for Anonymous requests")]),e._v(" "),n("p",[e._v("Java")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@GetMapping("/")\npublic String method(@CurrentSecurityContext SecurityContext context) {\n\treturn context.getAuthentication().getName();\n}\n')])])]),n("p",[e._v("Kotlin")]),e._v(" "),n("div",{staticClass:"language- extra-class"},[n("pre",{pre:!0,attrs:{class:"language-text"}},[n("code",[e._v('@GetMapping("/")\nfun method(@CurrentSecurityContext context : SecurityContext) : String =\n\t\tcontext!!.authentication!!.name\n')])])]),n("hr"),e._v(" "),n("p",[n("a",{attrs:{href:"#_footnoteref_1"}},[e._v("1")]),e._v(". The use of the "),n("code",[e._v("key")]),e._v(" property should not be regarded as providing any real security here. It is merely a book-keeping exercise. If you are sharing a "),n("code",[e._v("ProviderManager")]),e._v(" which contains an "),n("code",[e._v("AnonymousAuthenticationProvider")]),e._v(" in a scenario where it is possible for an authenticating client to construct the "),n("code",[e._v("Authentication")]),e._v(" object (such as with RMI invocations), then a malicious client could submit an "),n("code",[e._v("AnonymousAuthenticationToken")]),e._v(" which it had created itself (with chosen username and authority list). If the "),n("code",[e._v("key")]),e._v(" is guessable or can be found out, then the token would be accepted by the anonymous provider. This isn’t a problem with normal usage but if you are using RMI you would be best to use a customized "),n("code",[e._v("ProviderManager")]),e._v(" which omits the anonymous provider rather than sharing the one you use for your HTTP authentication mechanisms.")]),e._v(" "),n("p",[n("RouterLink",{attrs:{to:"/en/spring-security/openid.html"}},[e._v("OpenID")]),n("RouterLink",{attrs:{to:"/en/spring-security/preauth.html"}},[e._v("Pre-Authentication")])],1)])}),[],!1,null,null,null);t.default=o.exports}}]);