9.3. Authorization

9.3.1. Overview

This chapter explains authorization function provided by Spring Security.

Authorization process controls the resources that can be accessed by the users of the application. The standard method to control the resources that can be accessed by the user include defining an access policy for each resource (or a group of resources) and control the resources by checking the access policy when the user tries to access a resource.

Access policy defines whether to allow a user to access a particular resource. An access policy for following 3 types of resources is defined in Spring Security.

  • Web resource
  • Java method
  • Domain object [1]
  • Screen fields of JSP

This section introduces an implementation example (definition example) wherein authorization process is applied to access “Web resource”, “Java method” and “Screen fields of JSP” and explains the authorization function of Spring Security.

[1]For authorization function to access domain object , refer Spring Security Reference -Domain Object Security (ACLs)-.

9.3.1.1. Authorization process architecture

Spring Security performs authorization process as per the flow below.

../_images/AuthorizationArchitecture.png

Authorization process architecture

Sr. No. Description
(1)
A client accesses any resource.
(2)
FilterSecurityInterceptor class calls AccessDecisionManager interface method and checks whether the user has access rights for the resource.
(3)
AffirmativeBased class (Implementation class of AccessDecisionManager used as a default) calls AccessDecisionVoter interface method and votes for whether the user has access rights.
(4)
FilterSecurityInterceptor accesses the resource only if the access rights have been granted by AccessDecisionManager.

9.3.1.1.1. ExceptionTranslationFilter

ExceptionTranslationFilter is a security filter which handles exceptions generated by authorization process (AccessDecisionManager) and sends appropriate response to the client. In the default implementation, a response to ask for authentication in case of access by an unauthenticated user and a response to throw an authorization error in case of an authenticated user are returned.


9.3.1.1.2. FilterSecurityInterceptor

FilterSecurityInterceptor is a security filter to apply an authorization process for HTTP request and delegates actual authorization process to AccessDecisionManager. While calling a method of AccessDecisionManager interface, it is linked with the access policy specified in the resource which a client trying to access.


9.3.1.1.3. AccessDecisionManager

AccessDecisionManager interface checks whether the user has the access rights for the resource which he is trying to access.

Spring Security provides 3 types of implementation classes and all the classes call AccessDecisionVoter interface method and determine whether the access rights have been granted. AccessDecisionVoter votes for “Assign”, “Deny” or Abstain” and then implementation class of AccessDecisionManager aggregates the voting results and determines final access rights. AccessDeniedException exception is thrown and access is denied if determined as “no access rights”.

Note that, if all the voting results indicate “Abstain”, it is determined as “no access rights” in Spring Security by default.

Implementation class of AccessDecisionManager provided by Spring Security
Class name Description
AffirmativeBased
An implementation class which assigns the access rights when 1 vote is given to “Assign” during voting by AccessDecisionVoter.
Implementation class used as a default.
ConsensusBased
An implementation class which assigns the access rights when the majority of votes are for “Assign” during voting for all AccessDecisionVoter.
When 1 vote each is given to “Assign” and “Deny” or when it is a tie, it is considered as “Have access rights” by default in Spring Security.
UnanimousBased
An implementation class which does not give access rights when 1 vote is given to “Deny” during voting by AccessDecisionVoter.

Note

Selecting AccessDecisionVoter

If only one AccessDecisionVoter is used, no difference is observed in the operation regardless of the implementation class. When multiple AccessDecisionVoter are used, implementation class should be selected in accordance with the requirements.


9.3.1.1.4. AccessDecisionVoter

AccessDecisionVoter is an interface which checks the access policy specified in the resource which the user is trying to access and votes for whether the access rights are to be granted.

Main implementation classes provided by Spring Security are as given below.

Main implementation class of AccessDecisionVoter provided by Spring Security
Class name Description
WebExpressionVoter
An implementation class which carries out voting by checking the rights information retained by authentication information (Authentication) through SpEL and request information (HttpServletRequest).
RoleVoter
An implementation class which carries out voting by checking the role of the user.
RoleHierarchyVoter
An implementation class which carries out voting by checking the role hierarchy of a user.
AuthenticatedVoter
An implementation class which carries out voting by checking the authentication status.

Note

AccessDecisionVoter to be applied by default

Implementation class of AccessDecisionVoter interface applied by default is integrated with WebExpressionVoter from Spring Security 4.0 onwards. Since WebExpressionVoter can play the role similar to using RoleVoter,RoleHierarchyVoter and AuthenticatedVoter, this guideline will also assume the use of default WebExpressionVoter for explaining authorization process.


9.3.2. How to use

A bean definition example (how to specify an access policy) and implementation method required for using authorization function are explained.


9.3.2.1. How to describe an access policy

How to describe an access policy is explained.

Spring Security supports Spring Expression Language (SpEL) as a method which describes how to specify an access policy. Although there are other methods which do not use SpEL, this guideline explains how to specify an access policy by using Expression. How to use SpEL is briefly explained in this section, however for detailed description, refer Spring Framework Reference Documentation -Spring Expression Language (SpEL)-.


9.3.2.1.1. Built-In Common Expressions

Common Expressions provided by Spring Security are as given below.

Common Expression provided by Spring Security
Expression Description
hasRole(String role)
Return true when logged in user has a role specified in the argument.
hasAnyRole(String... roles)
Return true when logged in user has one of the roles specified in the argument.
isAnonymous()
Return true in case of an anonymous user who has not logged in.
isRememberMe()
Return true in case of a user logged in by using Remember Me authentication.
isAuthenticated()
Return true in case of a login.
isFullyAuthenticated()
Return true in case of a user who has logged in using normal authentication process instead of Remember Me authentication.
permitAll
Always return true.
denyAll
Always return false.
principal
Return user information of authenticated user (an object of a class which implements UserDetails interface).
authentication
Return authentication information of authenticated user (an object of a class which implements Authentication interface).

Note

Accessing authentication information which uses Expression

Since user information and authentication information of a logged in user can be accessed when principal and authentication are used as Expressions, an access policy can be set by using attributes other than role.

Note

Role name prefix

It was necessary to specify "ROLE_" prefix to role name till Spring Security 3.2. However, specifying "ROLE_" prefix is no longer required from Spring Security 4.0 onwards.

Example)

  • Before Spring Security 3.2 : hasRole('ROLE_USER')
  • Spring Security 4.0 onwards : hasRole('USER')

9.3.2.1.2. Built-In Web Expressions

Expressions for Web applications provided by Spring Security are as below.

Expressions for Web applications provided by Spring Security
Expression Description
hasIpAddress(String ipAddress)
Return truewhen requested IP address matches the IP address system specified in the argument.

9.3.2.1.3. Using operator

Determination using an operator can also be performed. In the example below, access can be granted if both role and requested IP address match.

  • Definition example of spring-security.xml

    <sec:http>
        <sec:intercept-url pattern="/admin/**" access="hasRole('ADMIN') and hasIpAddress('192.168.10.1')"/>
        <!-- omitted -->
    </sec:http>
    

    List of operators that can be used

    Operator Description
    [expression-1] and [expression-2]
    Return true when both expression-1 and expression-2 are true.
    [expression-1] or [expression-2]
    Return true when one of the expressions is true.
    ![expression]
    Return false when expression is true and return true when expression is false.

9.3.2.2. Authorization of Web resource

Spring Security performs authorization process for Web resource (HTTP request) using a servlet filter system.

9.3.2.2.1. Applying authorization process

Define a bean as below when authorization process is to be applied for a Web resource.

  • Definition example of spring-security.xml
<sec:http>
    <!-- omitted -->
    <sec:intercept-url pattern="/**" access="isAuthenticated()" />  <!-- (1) -->
    <!-- omitted -->
</sec:http>
Sr. No. Description
(1)
Define an access policy in <sec:intercept-url> tag for a HTTP request.
Here, an access policy is defined by using SpEL wherein “Only authenticated users are granted access for all the requests under a Web application”.

Note

Default definition of use-expressions

Since default value of use-expressions attribute of <sec:http> tag is changed to true from Spring Security 4.0 onwards, it is no longer necessary to explicitly describe while using true.

9.3.2.2.2. Defining access policy

How to define an access policy for a Web resource using a bean definition file is explained.

9.3.2.2.2.1. Specifying a Web resource for applying access policy

First, a resource (HTTP request) for which an access policy is to be applied, is specified. Attribute under <sec:intercept-url> tag is used for the specification of a resource for which an access policy is to be applied.

Attribute for specifying a resource for which an access policy is to be applied
Attribute name Description
pattern
An attribute which uses a resource matching with path pattern specified in Ant format or regular expression as an application target.
method
An attribute which uses a resource as an application target when access is to be done by using specified HTTP methods (GET, POST etc).
requires-channel
Specify “http” or “https”. An attribute for controlling the access by specified protocol.
if it is not specified, either of these can be accessed.

For the attributes other than above, refer <intercept-url>.

  • Definition example of <sec:intercept-url> tag pattern attribute (spring-security.xml)
<sec:http >
    <sec:intercept-url pattern="/admin/accounts/**" access="..."/>
    <sec:intercept-url pattern="/admin/**" access="..."/>
    <sec:intercept-url pattern="/**" access="..."/>
    <!-- omitted -->
</sec:http>

Spring Security matches the requests in the defined order and the definition which is matched at first is applied. Therefore, definition order must be taken into consideration even while specifying an access policy by using a bean definition file.

Tip

Interpretation of path pattern

Path pattern is interpreted in Ant format, in the default operation of Spring Security. When the path pattern is to be specified in the regular expression, "regex" should be specified in request-matcher attribute of <sec:http> tag

<sec:http request-matcher="regex">
    <sec:intercept-url pattern="/admin/accounts/.*" access=hasRole('ACCOUNT_MANAGER')" />
    <!-- omitted -->
</sec:http>

Warning

In Spring MVC and Spring Security, the mechanism of matching with the request is strictly different, and there is a vulnerability that breaks through the authorization function of Spring Security and can access the handler method using this difference. For details of this vulnerability, refer to “CVE-2016-5007 Spring Security / MVC Path Matching Inconsistency”.

In Spring Framework 4.3.1 and later, Spring Security 4.1.1 and later, this problem is solved by using MvcRequestMatcher , but in the Spring Framework 4.2.x used by TERASOLUNA Server Framework for Java (5.x), org.springframework.util.AntPathMatcher has to be used which set Spring MVC trimTokens property false .

<mvc:annotation-driven>
    <mvc:path-matching path-matcher="pathMatcher" />
</mvc:annotation-driven>

<bean id="pathMatcher" class="org.springframework.util.AntPathMatcher">
    <property name="trimTokens" value="false" />
</bean>

Although the above measures are set in blank projects that are provided by TERASOLUNA Server Framework for Java, it is necessary to be aware of it because it will be exposed to vulnerability if you remove the setting.

Further, if an access policy for a specific URL is to be specified (wild cards like *, ** etc are not included in pattern attribute), an access policy with a pattern with an extension and a pattern with / appended at the end of request path must be added.

In the following configuration example, only the users with “ROLE_ADMIN” role are allowed to access by /restrict.

<sec:http>
    <sec:intercept-url pattern="/restrict.*" access="hasRole('ADMIN')" /> <!-- (1) -->
    <sec:intercept-url pattern="/restrict/" access="hasRole('ADMIN')" /> <!-- (2) -->
    <sec:intercept-url pattern="/restrict" access="hasRole('ADMIN')" /> <!-- (3) -->
    <!-- omitted -->
</sec:http>
Sr. No. Description
(1)
Define an access policy of the pattern with an extension (/restrict.json etc) in /restrict.
(2)
Define an access policy of the pattern wherein / appended at the end of the request path (/restrict/ etc) in /restrict.
(3)
Define an access policy for /restrict.
9.3.2.2.2.2. Specifying an access policy

Next, an access policy is specified. Access policy is specified in access attribute of <sec:intercept-url> tag.

  • Definition example of <sec:intercept-url> tag access attribute (spring-security.xml)

    <sec:http>
        <sec:intercept-url pattern="/admin/accounts/**" access="hasRole('ACCOUNT_MANAGER')"/>
        <sec:intercept-url pattern="/admin/configurations/**" access="hasIpAddress('127.0.0.1') and hasRole('CONFIGURATION_MANAGER')" />
        <sec:intercept-url pattern="/admin/**" access="hasRole('ADMIN')" />
        <!-- omitted -->
    </sec:http>
    
    Attribute for specifying an access policy
    Attribute name Description
    access
    Specify access control expression using SpEL and a role that can be accessed.
A setting example with roles namely “ROLE_USER” and “ROLE_ADMIN” assigned to login user, is shown below.
  • Definition example of <sec:intercept-url> tag patternattribute (spring-security.xml)

    <sec:http>
        <sec:intercept-url pattern="/reserve/**" access="hasAnyRole('USER','ADMIN')" /> <!-- (1) -->
        <sec:intercept-url pattern="/admin/**" access="hasRole('ADMIN')" /> <!-- (2) -->
        <sec:intercept-url pattern="/**" access="denyAll" /> <!-- (3) -->
        <!-- omitted -->
    </sec:http>
    
    Sr. No. Description
    (1)
    To access “//reserve/**”, either the role “ROLE_USER” or “ROLE_ADMIN” is required.
    hasAnyRole will be described later.
    (2)
    To access “/admin/**”, the role “ROLE_ADMIN” is required.
    hasRole will be described later.
    (3)
    denyAll is set for all patterns
    Any user should not be able to access a URL for which no rights settings are described.
    denyAll will be described later.

    Note

    About description sequence of URL pattern

    The request received from client is matched with the pattern in intercept-url, starting from the top and access is granted for the matched pattern. Therefore, pattern should always be described from limited patterns.

SpEL is enabled in Spring Security by default. SpEL described in access attribute is determined as a true value. If the expression is true, access is granted. How to use is shown below.

  • Definition example of spring-security.xml

    <sec:http>
        <sec:intercept-url pattern="/admin/**" access="hasRole('ADMIN')"/>  <!-- (1) -->
        <!-- omitted -->
    </sec:http>
    
    Sr. No. Description
    (1)
    Return true if the logged in user retains the specified role, by specifying hasRole('Role name').

For main Expression that can be used, refer How to describe an access policy.


9.3.2.3. Authorization for the method

Spring Security performs authorization process for calling a method of Bean which is managed in DI container by using Spring AOP system.

Authorization process for the method is provided by considering its use for calling a domain layer (service layer) method. If authorization process for the method is used, a detailed access policy can be defined since a property of domain object can be checked.


9.3.2.3.1. Enabling AOP

When the authorization process for the method is to be used, a component (AOP) for performing authorization process for calling the method must be enabled. If AOP is enabled, access policy can be defined in the method annotation.

Spring Security supports following annotations.

  • @PreAuthorize, @PostAuthorize, @PreFilter, @PostFilter
  • JSR-250 (javax.annotation.security package) annotation (@RolesAllowed etc.)
  • @Secured

This guideline explains how to use @PreAuthorize and @PostAuthorize which enable the use of access policy by Expression.

  • Definition example of spring-security.xml
<sec:global-method-security pre-post-annotations="enabled" /> <!-- (1) (2) -->
Sr. No. Description
(1)
AOP which performs authorization process for method calling is enabled if <sec:global-method-security> tag is assigned.
(2)
Specify true in pre-post-annotations attribute.
If true is specified in pre-post-annotations attribute, the annotation that can define an access policy by specifying Expression is enabled.

9.3.2.3.2. Applying authorization process

An annotation which specifies an access policy is used and an access policy is defined for each method by applying authorization process for the method.

9.3.2.3.3. Defining access policy

9.3.2.3.3.1. Specifying an access policy to be applied prior to method execution

When an access policy is to be specified for applying prior to method execution, @PreAuthorize is used.

When the results of the Expression specified in value attribute of @PreAuthorize become true, execution of the method is allowed. In the example below, it has been defined that only administrator can access the account information for other persons.

  • Definition example of @PreAuthorize
// (1) (2)
@PreAuthorize("hasRole('ADMIN') or (#username == principal.username)")
public Account findOne(String username) {
    return accountRepository.findOne(username);
}
Sr. No. Description
(1)
Assign @PreAuthorize to the method which needs to be authorized.
(2)
Define an access policy for the method, in value attribute.
Here, an access policy - “Allow access to all accounts for the administrator” and “Allow access to only individual account when other than administrator” is defined.

The part wherein a method argument is accessed from the Expression is discussed here. Specifically, “#username” part accesses the argument. A method argument can be accessed by specifying Expression of “# + argument name” format in Expression.

Tip

Annotation which specifies argument name

Spring Security resolves the argument name from debug information output in the class. However an argument name can be explicitly specified by using an annotation (@org.springframework.security.access.method.P)

A variable name can be specified explicitly by using the annotation if it is applicable to following cases.

  • Debug information of variable is not output in the class

  • When it is to be accessed by using a name different from that of actual variable name in the Expression (for example shortened name)

    @PreAuthorize("hasRole('ADMIN') or (#username == principal.username)")
    public Account findOne(@P("username") String username) {
        return accountRepository.findOne(username);
    }
    

Note that when #username and a method argument - username name are identical, @P can be omitted. However, since Spring Security resolves the argument name by using an argument name of implementation class, note that the argument name of implementation class should match with #username specified in @PreAuthorize when @PreAuthorize annotation is defined in the interface.

When compile option added from JDK 8 (-parameters) is used, meta data for reflection is generated in the method parameter. Hence argument name is resolved even when the annotation is not specified.

9.3.2.3.3.2. Specifying access policy to be applied after method execution

When an access policy to be applied after execution of the method is specified, @PostAuthorize is used.

When the results of the Expression specified in value attribute of @PostAuthorize become true, results of method execution are returned to the call source. In the example below, it has been defined such that the user is not allowed to access the information of the user belonging to other department.

  • Definition example of @PostAuthorize
@PreAuthorize("...")
@PostAuthorize("(returnObject == null) " +
        "or (returnObject.departmentCode == principal.account.departmentCode)")
public Account findOne(String username) {
    return accountRepository.findOne(username);
}

The part wherein the return value of the method is accessed from the Expression is discussed here. Specifically, “returnObject.departmentCode” part accesses the return value. The return value of the method can be accessed by specifying returnObject in the Expression.


9.3.2.4. Authorization for JSP screen fields

Spring Security can apply authorization process for JSP screen fields by using a JSP tag library.

Here, a method to apply authorization process for accessing JSP screen fields is explained using a simple definition as an example.


9.3.2.4.1. Defining an access policy

A condition to allow display (access policy) is defined in JSP while defining an access policy for JSP screen fields using a JSP tag library.

  • Definition example of access policy
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>

<!-- (1) -->
<sec:authorize access="hasRole('ADMIN')"> <!-- (2) -->
    <h2>Admin Menu</h2>
    <!-- omitted -->
</sec:authorize>
Sr. No. Description
(1)
Enclose part for which an access policy is to be applied with <sec:authorize> tag.
(2)
Define an access policy in access attribute. Here, an access policy - “allow display in case of administrator” is defined.

9.3.2.4.2. Linking with the access policy specified in the Web resource

When an access policy is to be defined for buttons or links (screen fields associated with the requests to the server), it is linked with an access policy defined in the Web resource for request. url attribute of <sec:authorize> tag is used for linking with access policy specified in the Web resource.

JSP process implemented in <sec:authorize> tag is executed only when Web resource specified in url attribute can be accessed.

  • Example of linking with access policy defined in Web resource
<ul>
    <!-- (1) -->
    <sec:authorize url="/admin/accounts"> <!-- (2) -->
        <li>
            <a href="<c:url value='/admin/accounts' />">Account Management</a>
        </li>
    </sec:authorize>
</ul>
Sr. No. Description
(1)
Enclose part which outputs button or link with <sec:authorize> tag.
(2)
Specify a URL for accessing a Web resource in url attribute of <sec:authorize> tag.
Here, an access policy - “Allow display when a Web resource allocated with "/admin/accounts" URL can be accessed” is defined however it is not necessary to be directly aware of the access policy defined in Web resource.

Note

Specifying a policy by HTTP method

When a different access policy is specified by HTTP method while defining an access policy of Web resource, the definition to be linked must be identified by using method attribute of <sec:authorize> tag.

Warning

Notes related to display control

When display for a button or link is to be controlled, it should always be linked with an access policy defined in the Web resource.

If an access policy is not defined independently for a Web resource by specifying a direct access policy for button or link, an unauthorized access such as accessing a URL directly cannot be prevented.


9.3.2.4.3. Storing determination results of authorization process in the variable

Determination results of authorization process called by using <sec:authorize> tag can be reused by storing in the variable.

  • Implementation example of JSP
<sec:authorize url="/admin/accounts"
               var="hasAccountsAuthority"/> <!-- (1) -->

<c:if test="${hasAccountsAuthority}"> <!-- (2) -->
    <!-- omitted -->
</c:if>
Sr. No. Description
(1)
Specify a variable name for storing determination results in var attribute.
When access is allowed, true is set in the variable.
(2)
Refer variable value and implement display process.

9.3.2.5. Response at the time of authorization error

Spring Security handles the errors as shown in the following flow and controls the response when access to a resource is denied.

../_images/AuthorizationAccessDeniedHandling.png

Mechanism for handling authorization error

Sr. No. Description
(1)
Spring Security generates a AccessDeniedException for denying access to a resource or a method.
(2)
ExceptionTranslationFilter class catches AccessDeniedException and performs error handling by calling methods of AccessDeniedHandler or AuthenticationEntryPoint interface.
(3)
Perform error handling by calling a method of AccessDeniedHandler interface in case of an access by authenticated user.
(4)
Perform error handling by calling a method of AuthenticationEntryPoint interface in case of an access by unauthenticated user.

9.3.2.5.1. AccessDeniedHandler

AccessDeniedHandler interface handles the error responses when the access is denied to authenticated users. Spring Security offers following classes as the implementation class of AccessDeniedHandler interface.

Implementation class of AccessDeniedHandler provided by Spring Security
Class name Description
AccessDeniedHandlerImpl
Set 403 (Forbidden) in HTTP response code and move to specified error page.
When error page is not specified, send error response (HttpServletResponse#sendError) by setting 403 (Forbidden) in HTTP response code.
InvalidSessionAccessDeniedHandler
Delegate the process to implementation class of InvalidSessionStrategy interface.
This class is used when the settings to detect a session timeout is enabled by using CSRF countermeasure and session management function at the time when CSRF token does not exist in the session (a session timeout has occurred).
DelegatingAccessDeniedHandler
Map implementation classes of AccessDeniedException and AccessDeniedHandler interface and delegate the process to the implementation class of AccessDeniedHandler interface corresponding to AccessDeniedException thus occurred.
InvalidSessionAccessDeniedHandler is called by using this mechanism.

In the default setting of Spring Security, AccessDeniedHandlerImplis used wherein an error page is not specified.


9.3.2.5.2. AuthenticationEntryPoint

AuthenticationEntryPoint interface handles the error responses when the access is denied to unauthenticated users. Spring Security offers following class as an implementation class of AuthenticationEntryPoint interface.

Main implementation class of AuthenticationEntryPoint offered by Spring Security
Class Name Description
LoginUrlAuthenticationEntryPoint
Display a login form for form authentication.
BasicAuthenticationEntryPoint
Send error response for Basic authentication.
Specifically, set 401 (Unauthorized) in HTTP response code, WWW-Authenticate header for Basic authentication as a response header and send error response (HttpServletResponse#sendError).
DigestAuthenticationEntryPoint
Send error response for Digest authentication.
Specifically, set 401 (Unauthorised) in the HTTP response code, WWW-Authenticate header for Digest authentication as a response header and send error response (HttpServletResponse#sendError).
Http403ForbiddenEntryPoint
Set 403 (Forbidden) in HTTP response code and send error response (HttpServletResponse#sendError).
DelegatingAuthenticationEntryPoint
Map implementation class of RequestMatcher and AuthenticationEntryPoint interface, and delegate the process to implementation class of AuthenticationEntryPoint interface corresponding to HTTP request.

Implementation class of AuthenticationEntryPoint interface corresponding to authentication method is used in the default setup of Spring Security.


9.3.2.5.3. Transition destination at the time of authorization error

In the default setting of Spring Security, when the access is denied to the authenticated user, an error page of application server is displayed. If error page of application server is displayed, it is likely to result in system degradation. Hence it is recommended to display an appropriate error screen. Error page can be specified by defining a bean as below.

  • Definition example of spring-security.xml
<sec:http>
    <!-- omitted -->
    <sec:access-denied-handler
        error-page="/WEB-INF/views/common/error/accessDeniedError.jsp" /> <!-- (1) -->
    <!-- omitted -->
</sec:http>
Sr. No. Description
(1)
Specify an error page for authorization error in error-page attribute of <sec:access-denied-handler> tag.

Tip

Using error page function of servlet container

Error page for authorization error can also be specified by using an error page function of servlet container.

When error page function of servlet container is used, error page is specified by using <error-page> tag of web.xml.

<error-page>
    <error-code>403</error-code>
    <location>/WEB-INF/views/common/error/accessDeniedError.jsp</location>
</error-page>

9.3.3. How to extend

This section explains customization points and extension methods offered by Spring Security.

Spring Security provides a lot of customization points of which only a few will be introduced here. This section will focus on some typical customization points.


9.3.3.1. Response at the time of authorization error (Authenticated user)

Here, a method to customise the operation when an access from authenticated user is denied, is explained.

9.3.3.1.1. Applying AccessDeniedHandler

When the requirements are not met only by customising default operation provided by Spring Security, implementation class of AccessDeniedHandler interface can be directly applied.

For example, when an authorization error occurs in Ajax request (REST API etc), error information is displayed in JSON format instead of displaying an error page (HTML). In such a case, an implementation class of AccessDeniedHandler interface can be created and applied in Spring Security.

  • How to create an implementation class of AccessDeniedHandler interface
public class JsonDelegatingAccessDeniedHandler implements AccessDeniedHandler {

    private final RequestMatcher jsonRequestMatcher;
    private final AccessDeniedHandler delegateHandler;

    public JsonDelegatingAccessDeniedHandler(
            RequestMatcher jsonRequestMatcher, AccessDeniedHandler delegateHandler) {
        this.jsonRequestMatcher = jsonRequestMatcher;
        this.delegateHandler = delegateHandler;
    }

    public void handle(HttpServletRequest request, HttpServletResponse response,
                       AccessDeniedException accessDeniedException)
            throws IOException, ServletException {
        if (jsonRequestMatcher.matches(request)) {
            // response error information of JSON format
            response.setStatus(HttpServletResponse.SC_FORBIDDEN);
            // omitted
        } else {
            // response error page of HTML format
            delegateHandler.handle(
                    request, response, accessDeniedException);
        }
    }

}
  • Definition example of spring-security.xml
<!-- (1) -->
<bean id="accessDeniedHandler"
      class="com.example.web.security.JsonDelegatingAccessDeniedHandler">
    <constructor-arg>
        <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
            <constructor-arg value="/api/**"/>
        </bean>
    </constructor-arg>
    <constructor-arg>
        <bean class="org.springframework.security.web.access.AccessDeniedHandlerImpl">
            <property name="errorPage"
                      value="/WEB-INF/views/common/error/accessDeniedError.jsp"/>
        </bean>
    </constructor-arg>
</bean>

<sec:http>
    <!-- omitted -->
    <sec:access-denied-handler ref="accessDeniedHandler" />  <!-- (2) -->
    <!-- omitted -->
</sec:http>
Sr. No. Description
(1) Define a bean for implementation class of AccessDeniedHandler interface and register in DI container.
(2) Specify a bean for AccessDeniedHandler in ref attribute of <sec:access-denied-handler> tag.

9.3.3.2. Response at the time of authorization error (Unauthenticated user)

Here, a method to customise operation when access is denied to an unauthenticated user, is explained.

9.3.3.2.1. Applying AuthenticationEntryPoint for each request

Similarly to authenticated user, when authorization error occurs in Ajax request (REST API etc), error information is displayed in JSON format instead of displaying it in login page (HTML). In such a case, implementation class of AuthenticationEntryPoint interface for each pattern of request is applied in Spring Security.

  • Definition example of spring-security.xml
<!-- (1) -->
<bean id="authenticationEntryPoint"
      class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint">
    <constructor-arg>
        <map>
            <entry>
                <key>
                    <bean class="org.springframework.security.web.util.matcher.AntPathRequestMatcher">
                        <constructor-arg value="/api/**"/>
                    </bean>
                </key>
                <bean class="com.example.web.security.JsonAuthenticationEntryPoint"/>
            </entry>
        </map>
    </constructor-arg>
    <property name="defaultEntryPoint">
        <bean class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint">
            <constructor-arg value="/login"/>
        </bean>
    </property>
</bean>

<sec:http entry-point-ref="authenticationEntryPoint"> <!-- (2) -->
    <!-- omitted -->
</sec:http>
Sr. No. Description
(1)
Define a bean for implementation class of AuthenticationEntryPoint interface and register in DI container.
Here, an implementation class of AuthenticationEntryPoint interface is applied for each pattern of request by using DelegatingAuthenticationEntryPoint class offered by Spring Security.
(2)
Specify a bean for AuthenticationEntryPointin entry-point-ref attribute of <sec:http> tag.

Note

AuthenticationEntryPoint applied by default

When the implementation class of AuthenticationEntryPoint interface corresponding to request is not specified, the implementation class of AuthenticationEntryPoint interface defined by Spring Security by default is used. When form authentication is used as an authentication method, LoginUrlAuthenticationEntryPoint class is used and login form is displayed.


9.3.3.3. Role hierarchy

A hierarchy can be set for a role in the authorization process.

Higher level roles can also access the resources for which access is granted to the lower level roles. When the role relation is complex, hierarchy relation must also be established.

For example, when a hierarchy relation is established wherein “ROLE_ADMIN” is a higher role and “ROLE_USER” is a lower role, and if an access policy is set as below, user with “ROLE_ADMIN” rights can access a path under "/user"(a path which can be accessed by a user with “ROLE_USER” rights).

  • Definition example of spring-security.xml
<sec:http>
    <sec:intercept-url pattern="/user/**" access="hasAnyRole('USER')" />
    <!-- omitted -->
</sec:http>

9.3.3.3.1. Setting hierarchy relation

Role hierarchy relation is resolved by using implementation class of org.springframework.security.access.hierarchicalroles.RoleHierarchy interface.

  • Definition example of spring-security.xml
<bean id="roleHierarchy"
    class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl"> <!-- (1) -->
    <property name="hierarchy"> <!-- (2) -->
        <value>
            ROLE_ADMIN > ROLE_STAFF
            ROLE_STAFF > ROLE_USER
        </value>
    </property>
</bean>
Sr. No. Description
(1)
Specify org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl class.
RoleHierarchyImpl is a default implementation class offered by Spring Security.
(2)
Define the hierarchy relation in hierarchy property.

Format : [Higher role] > [Lower role]

In the example above,
STAFF can also access resources authorised by USER.
ADMIN can also access resources authorised by USER and STAFF.

9.3.3.3.2. Applying authorization process of Web resource

A method to apply role hierarchy to authorization process for Web resource and JSP screen fields is explained.

  • Definition example of spring-security.xml

    <!-- (1) -->
    <bean id="webExpressionHandler"
        class="org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler">
        <property name="roleHierarchy" ref="roleHierarchy"/>  <!-- (2) -->
    </bean>
    
    <sec:http>
        <!-- omitted -->
        <sec:expression-handler ref="webExpressionHandler" />  <!-- (3) -->
    </sec:http>
    
Sr. No.
Explanation
(1)
Define a Bean for org.springframework.security.web.access.expression.DefaultWebSecurityExpressionHandler.
(2)
Specify a Bean for implementation class of RoleHierarchy interface in roleHierarchy property.
(3)
Specify a Bean for implementation class of org.springframework.security.access.expression.SecurityExpressionHandler interface in ref attribute of <sec:expression-handler> tag.

9.3.3.3.3. Applying authorization process of method

A method to apply role hierarchy to authorization process for Java method is explained.

  • Definition example of spring-security.xml
<bean id="methodExpressionHandler"
    class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler"> <!-- (1) -->
    <property name="roleHierarchy" ref="roleHierarchy"/> <!-- (2) -->
</bean>

<sec:global-method-security pre-post-annotations="enabled">
    <sec:expression-handler ref="methodExpressionHandler" /> <!-- (3) -->
</sec:global-method-security>
Sr. No. Description
(1)
Define a Bean for org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler.
(2)
Specify a Bean for implementation class of RoleHierarchy interface in roleHierarchy property.
(3)
Specify a Bean for implementation class of org.springframework.security.access.expression.SecurityExpressionHandler interface in ref attribute of <sec:expression-handler> tag.