{"id":740,"date":"2012-02-19T18:27:44","date_gmt":"2012-02-19T17:27:44","guid":{"rendered":"http:\/\/doanduyhai.wordpress.com\/?p=740"},"modified":"2012-02-19T18:27:44","modified_gmt":"2012-02-19T17:27:44","slug":"spring-security-part-iv-exceptiontranslationfilter-filtersecurityinterceptor","status":"publish","type":"post","link":"https:\/\/www.doanduyhai.com\/blog\/?p=740","title":{"rendered":"Spring Security part IV : ExceptionTranslationFilter &#038; FilterSecurityInterceptor"},"content":{"rendered":"<p>In this post we&#8217;ll examine in depth the <strong>ExceptionTranslationFilter<\/strong> and <strong>FilterSecurityInterceptor<\/strong> filters<\/p>\n<p><!--more--><\/p>\n<h1>VII ExceptionTranslationFilter<\/h1>\n<pre class=\"brush: xml; title: ; toolbar: true; wrap-lines: false; notranslate\" title=\"\">\n&amp;lt;!-- Filter to redirect to login page --&amp;gt;\n&amp;lt;bean id=&amp;quot;exceptionTranslationFilter&amp;quot; class=&amp;quot;org.springframework.security.web.access.ExceptionTranslationFilter&amp;quot;&amp;gt;\n        &amp;lt;property name=&amp;quot;authenticationEntryPoint&amp;quot; ref=&amp;quot;authenticationEntryPoint&amp;quot;\/&amp;gt;\n        &amp;lt;property name=&amp;quot;accessDeniedHandler&amp;quot; ref=&amp;quot;accessDeniedHandler&amp;quot;\/&amp;gt;\n&amp;lt;\/bean&amp;gt;\n    \n&amp;lt;bean id=&amp;quot;authenticationEntryPoint&amp;quot;  class=&amp;quot;org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint&amp;quot;&amp;gt;\n\t  &amp;lt;property name=&amp;quot;loginFormUrl&amp;quot; value=&amp;quot;\/pages\/Security\/login.html&amp;quot;\/&amp;gt;\n\t  &amp;lt;property name=&amp;quot;forceHttps&amp;quot; value=&amp;quot;false&amp;quot;\/&amp;gt;\n&amp;lt;\/bean&amp;gt;\n    \n&amp;lt;bean id=&amp;quot;accessDeniedHandler&amp;quot; class=&amp;quot;org.springframework.security.web.access.AccessDeniedHandlerImpl&amp;quot;&amp;gt;\n\t&amp;lt;property name=&amp;quot;errorPage&amp;quot; value=&amp;quot;\/pages\/Security\/accessDenied.html&amp;quot;\/&amp;gt;\n&amp;lt;\/bean&amp;gt;\n<\/pre>\n<h4>1) ExceptionTranslationFilter<\/h4>\n<p>The <strong>ExceptionTranslationFilter<\/strong> purpose is to redirect the user to the login page if he&#8217;s not yet authenticated and to a default error page if he tries to access an unauthorized resources.<\/p>\n<p>The <strong>authenticationEntryPoint<\/strong> defines a <em>loginFormUrl<\/em> pointing to the default login page. Optionally you can force usage of HTTPS by setting <em>forceHttps<\/em> to <strong>true<\/strong>.<\/p>\n<p>Your login page should resemble:<\/p>\n<pre class=\"brush: xml; highlight: [1,5,8]; title: ; toolbar: true; wrap-lines: false; notranslate\" title=\"\">\n&amp;lt;form action=&amp;quot;myApplication\/j_myApplication_security_check&amp;quot; method=&amp;quot;post&amp;quot;&amp;gt;\n\t&amp;lt;fieldset&amp;gt;\n\t\t&amp;lt;legend&amp;gt;Login form&amp;lt;\/legend&amp;gt;\n\t\t&amp;lt;label for=&amp;quot;j_username&amp;quot;&amp;gt;Login&amp;lt;\/label&amp;gt;\n\t\t&amp;lt;input type=&amp;quot;text&amp;quot; id=&amp;quot;j_username&amp;quot; size=&amp;quot;20&amp;quot;\/&amp;gt;\n\n\t\t&amp;lt;label for=&amp;quot;j_password&amp;quot;&amp;gt;Password&amp;lt;\/label&amp;gt;\n\t\t&amp;lt;input type=&amp;quot;password&amp;quot; id=&amp;quot;j_password&amp;quot; size=&amp;quot;20&amp;quot;\/&amp;gt;\n\t\t\t\n\t\t&amp;lt;button type=&amp;quot;submit&amp;quot;&amp;gt;Submit&amp;lt;\/button&amp;gt;\n\t\t&amp;lt;button type=&amp;quot;reset&amp;quot;&amp;gt;Reset&amp;lt;\/button&amp;gt;\n\t&amp;lt;\/fieldset&amp;gt;\t\t\n&amp;lt;\/form&amp;gt;\n<\/pre>\n<p>Remember about the <em>filterProcessesUrl<\/em> parameter we mentionned in the previous post ? It is used here as default action for the login form.<\/p>\n<p> For Spring Security to retrieve the login &amp; password values in the HTTP request attributes, we should set their ids to &#8220;<em>j_username<\/em>&#8221; &amp; &#8220;<em>j_password<\/em>&#8221; respectively. This is the <strong>default convention<\/strong>.<\/p>\n<p> Again it is possible to change these defaults by setting the &#8220;<em>usernameParameter<\/em>&#8221; &amp; &#8220;<em>passwordParameter<\/em>&#8221; for the <strong>authenticationProcessingFilter<\/strong>.<\/p>\n<pre class=\"brush: xml; highlight: [3,4,5]; title: ; toolbar: true; wrap-lines: false; notranslate\" title=\"\">\n&amp;lt;bean id=&amp;quot;authenticationProcessingFilter&amp;quot; class=&amp;quot;org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter&amp;quot;&amp;gt;\n\t&amp;lt;property name=&amp;quot;authenticationManager&amp;quot; ref=&amp;quot;authenticationManager&amp;quot;\/&amp;gt;\n\t&amp;lt;property name=&amp;quot;usernameParameter&amp;quot; value=&amp;quot;j_myUserNameId&amp;quot;\/&amp;gt;\n\t&amp;lt;property name=&amp;quot;passwordParameter&amp;quot; value=&amp;quot;j_myPasswordId&amp;quot;\/&amp;gt;\n\t&amp;lt;property name=&amp;quot;filterProcessesUrl&amp;quot; value=&amp;quot;\/j_myApplication_security_check&amp;quot;\/&amp;gt;\n\t...\n&amp;lt;\/bean&amp;gt;\n<\/pre>\n<p>&nbsp;<\/p>\n<h4>2) AccessDeniedHandler<\/h4>\n<p>This handler simply forwards the user to the error page defined by the &#8220;<em>errorPage<\/em>&#8221; parameter if he is not authorized to access the requested resources, quite straightforward.<\/p>\n<p>&nbsp;<\/p>\n<h1>VIII FilterSecurityInterceptor<\/h1>\n<p>The core of access management is done by this filter.<br \/>\n First, the namespace for Spring security should be set in order to use the shorthand &#8220;<em>sec<\/em>&#8220;.<\/p>\n<pre class=\"brush: xml; highlight: [3]; title: ; toolbar: true; wrap-lines: false; notranslate\" title=\"\">\n&amp;lt;beans xmlns=&amp;quot;http:\/\/www.springframework.org\/schema\/beans&amp;quot;\n\txmlns:xsi=&amp;quot;http:\/\/www.w3.org\/2001\/XMLSchema-instance&amp;quot;\n \txmlns:sec=&amp;quot;http:\/\/www.springframework.org\/schema\/security&amp;quot;\n\txsi:schemaLocation=&amp;quot;http:\/\/www.springframework.org\/schema\/beans http:\/\/www.springframework.org\/schema\/beans\/spring-beans-3.0.xsd\n\t\thttp:\/\/www.springframework.org\/schema\/security http:\/\/www.springframework.org\/schema\/security\/spring-security-3.0.xsd&amp;quot;&amp;gt;\n<\/pre>\n<h4>1) &lt;sec:filter-security-metadata-source&gt;<\/h4>\n<pre class=\"brush: xml; highlight: [4,8,9,12,14]; title: ; toolbar: true; wrap-lines: false; notranslate\" title=\"\">\n&amp;lt;!-- Filter for role checking --&amp;gt;\n&amp;lt;bean id=&amp;quot;filterSecurityInterceptor&amp;quot; class=&amp;quot;org.springframework.security.web.access.intercept.FilterSecurityInterceptor&amp;quot;&amp;gt;\n\t&amp;lt;property name=&amp;quot;authenticationManager&amp;quot; ref=&amp;quot;authenticationManager&amp;quot;\/&amp;gt;\n\t&amp;lt;property name=&amp;quot;accessDecisionManager&amp;quot; ref=&amp;quot;httpRequestAccessDecisionManager&amp;quot;\/&amp;gt;\n\t&amp;lt;property name=&amp;quot;securityMetadataSource&amp;quot;&amp;gt;\n\t\t&amp;lt;sec:filter-security-metadata-source lowercase-comparisons=&amp;quot;true&amp;quot; request-matcher=&amp;quot;ant&amp;quot; use-expressions=&amp;quot;true&amp;quot;&amp;gt;\n\t\t\t&amp;lt;sec:intercept-url pattern=&amp;quot;\/pages\/Security\/**&amp;quot; access=&amp;quot;permitAll&amp;quot;\/&amp;gt;\n\t\t\t&amp;lt;sec:intercept-url pattern=&amp;quot;\/resources\/**&amp;quot; access=&amp;quot;permitAll&amp;quot;\/&amp;gt;\n\t\t\t&amp;lt;sec:intercept-url pattern=&amp;quot;\/pages\/Settings\/**&amp;quot; access=&amp;quot;hasRole('SETTINGS')&amp;quot;\/&amp;gt;\n\t\t\t&amp;lt;sec:intercept-url pattern=&amp;quot;\/pages\/Home\/*&amp;quot; access=&amp;quot;hasRole('HOME')&amp;quot;\/&amp;gt;              \n\t\t\t&amp;lt;sec:intercept-url pattern=&amp;quot;\/pages\/Admin\/**&amp;quot; access=&amp;quot;hasRole('ADMINISTRATOR')&amp;quot;\/&amp;gt;\n\t\t\t&amp;lt;sec:intercept-url pattern=&amp;quot;\/servlet\/Download&amp;quot; access=&amp;quot;hasAnyRole('DOWNLOAD','PREMIUM_ACCOUNT')&amp;quot;\/&amp;gt;\n                \n\t\t\t&amp;lt;sec:intercept-url pattern=&amp;quot;\/**&amp;quot; access=&amp;quot;isAuthenticated()&amp;quot;\/&amp;gt;\n\t\t&amp;lt;\/sec:filter-security-metadata-source&amp;gt;\n\t&amp;lt;\/property&amp;gt;\n&amp;lt;\/bean&amp;gt;\n<\/pre>\n<p>Lots of interesting points to mention here.<\/p>\n<p>We define inside the <strong>&lt;filter-security-metadata-source&gt;<\/strong> tag a list of resource URLs and the corresponding roles to access them. This tag exposes the following attributes:<\/p>\n<ul>\n<li><strong>lowercase-comparisons<\/strong> : if <strong>true<\/strong> Spring will compare paths after forcing to lowercase<\/li>\n<li><strong>request-matcher<\/strong> : defines the pattern matching style for incoming URLs. Possible values are <strong>ant<\/strong>, <strong>regexp<\/strong> &amp; <strong>ciRegex<\/strong><\/li>\n<li><strong>use-expressions<\/strong>: if <strong>true<\/strong>, Spring will enable the use of expressions (like <em>hasRole()<\/em>) in the &#8216;<em>access<\/em>&#8216; attributes in <strong>&lt;intercept-url&gt;<\/strong> elements<\/li>\n<\/ul>\n<p>At <strong>line 8<\/strong>, we allow un-authenticated access to theme resources (<em>css, images, javascripts<\/em>) by setting <strong>access=&#8221;permitAll&#8221;<\/strong>. Similarly, all pages in &#8220;<em>\/pages\/Security<\/em>&#8221; folder, <strong>including login form<\/strong>, are granted the permitAll access (otherwise the user can never reach the login form).<\/p>\n<p>At <strong>line 9<\/strong>, accessing all pages in &#8220;<em>\/pages\/Settings<\/em>&#8221; subfolder requires the role <strong>SETTINGS<\/strong>. The role definition relies on the <strong>hasRole(String)<\/strong> expression. A comprehensive list of all available expressions for access control is documented here <a href=\"http:\/\/static.springsource.org\/spring-security\/site\/docs\/3.0.x\/reference\/el-access.html\" title=\"http:\/\/static.springsource.org\/spring-security\/site\/docs\/3.0.x\/reference\/el-access.html\" target=\"_blank\">Expression-Based Access Control<\/a><\/p>\n<p>At <strong>line 12<\/strong> we have an example of access control base on a list of roles using the <strong>hasAnyRole()<\/strong> expression.<\/p>\n<p>Finally, at <strong>line 14<\/strong>, we restrict the access to all of our application resources (path = <em>&#8220;\/**&#8221;<\/em>) by requiring that the user should be authenticated (<strong>not anonymous<\/strong>).<\/p>\n<p>There is an important gotcha with the above access control definition. <strong>Spring will apply access control rules in their declaration order<\/strong>. Consequently it is important to declare first all un-secured resources and finish with the most restricted resources.<\/p>\n<p>For example, if we had declared <strong>&lt;sec:intercept-url pattern=&#8221;\/**&#8221; access=&#8221;isAuthenticated()&#8221;\/&gt;<\/strong> before <strong>&lt;sec:intercept-url pattern=&#8221;\/pages\/Security\/**&#8221; access=&#8221;permitAll&#8221;\/&gt;<\/strong>, the application will never be accessible since on entering the login form, the user is rejected because not authenticated.<\/p>\n<p>&nbsp;<\/p>\n<h4>2) AccessDecisionManager<\/h4>\n<p>Above we just define access control rules for incoming URLs. Still we need a manager to enforce these rules and there comes the <strong>AccessDecisionManager<\/strong> into play.<\/p>\n<pre class=\"brush: xml; highlight: [2,3]; title: ; toolbar: true; wrap-lines: false; notranslate\" title=\"\">\n&amp;lt;bean id=&amp;quot;httpRequestAccessDecisionManager&amp;quot; \n\tclass=&amp;quot;org.springframework.security.access.vote.AffirmativeBased&amp;quot;&amp;gt;\n\t&amp;lt;property name=&amp;quot;allowIfAllAbstainDecisions&amp;quot; value=&amp;quot;false&amp;quot;\/&amp;gt;\n\t&amp;lt;property name=&amp;quot;decisionVoters&amp;quot;&amp;gt;\n\t\t&amp;lt;list&amp;gt;\n\t\t\t&amp;lt;ref bean=&amp;quot;webExpressionVoter&amp;quot;\/&amp;gt;\n\t\t\t&amp;lt;ref bean=&amp;quot;authenticatedVoter&amp;quot;\/&amp;gt;\n\t\t&amp;lt;\/list&amp;gt;\n\t&amp;lt;\/property&amp;gt;\n&amp;lt;\/bean&amp;gt;\n    \n&amp;lt;bean id=&amp;quot;webExpressionVoter&amp;quot; \n\tclass=&amp;quot;org.springframework.security.web.access.expression.WebExpressionVoter&amp;quot;\/&amp;gt;\n&amp;lt;bean id=&amp;quot;authenticatedVoter&amp;quot; \n\tclass=&amp;quot;org.springframework.security.access.vote.AuthenticatedVoter&amp;quot; \/&amp;gt;\n<\/pre>\n<p>First we use the <strong>org.springframework.security.access.vote.AffirmativeBased<\/strong> provided by Spring to control access rules. This default implementation of the <strong>AccessDecisionManager<\/strong> interface simply grants access if <strong>any<\/strong> injected <em>decisionVoters<\/em> returns an affirmative response.<\/p>\n<p>Two other implementations of the <strong>AccessDecisionManager<\/strong> interface are available:<\/p>\n<ul>\n<li><strong>ConsensusBased<\/strong>: access is granted if a <strong>majority<\/strong> of decision voters return an affirmative response<\/li>\n<li><strong>UnanimousBased<\/strong>: access is granted only if <strong>all<\/strong> decision voters return an affirmative response<\/li>\n<\/ul>\n<p>The <strong>allowIfAllAbstainDecisions<\/strong> property on the is set to false so that <strong>at least one<\/strong> affirmative response is required from decision voters to grant access.<\/p>\n<p>Next we inject two decision voters into this <strong>AccessDecisionManager<\/strong>:<\/p>\n<ul>\n<li><strong>WebExpressionVoter<\/strong>: grant access using Expression-Based Access Control as mentioned above. This voter is mandatory if we have specified use-expressions = true for the <strong>&lt;filter-security-metadata-source&gt;<\/strong><\/li>\n<li><strong>AuthenticatedVoter<\/strong>: default voter. This voter will give affirmative response if the user is <strong>authenticated<\/strong>, authenticated with <strong>remember-me<\/strong> option or is authenticated <strong>anonymously<\/strong><\/li>\n<\/ul>\n<p> There are some other implementations of the <strong>AccessDecisionVoter<\/strong> interface provided by Spring, we just mention them for information:<\/p>\n<ul>\n<li><strong>Jsr250Voter<\/strong>: voter compatible with the JSR 250 security annotations\n<ul>\n<li>@RunAs<\/li>\n<li>@RolesAllowed<\/li>\n<li>@PermitAll<\/li>\n<li>@DenyAll<\/li>\n<li>@DeclareRoles<\/li>\n<\/ul>\n<\/li>\n<li><strong>RoleVoter<\/strong>: the equivalent to <strong>WebExpressionsVoter<\/strong> but using user roles to take decisions. The access is granted if the user role label starts with &#8220;<strong>ROLE_<\/strong>&#8220;.This default prefix can be changed by overriding the <em>rolePrefix<\/em> property.<\/li>\n<li><strong>AclEntryVoter<\/strong>: voter using an ACL list<\/li>\n<\/ul>\n","protected":false},"excerpt":{"rendered":"<p>In this post we&#8217;ll examine in depth the ExceptionTranslationFilter and FilterSecurityInterceptor filters<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[30,14],"tags":[],"_links":{"self":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/740"}],"collection":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=740"}],"version-history":[{"count":0,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=\/wp\/v2\/posts\/740\/revisions"}],"wp:attachment":[{"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=740"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=740"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.doanduyhai.com\/blog\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=740"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}