What's the best way to implement authorization / access control in a Spring 3 MVC web application?

Friends,

I am going to develop a web application using Spring 3 MVC as web framework, Hibernate annotation as ORM framework. However, I am having a problem developing good database based access control for this application. In my work, we develop this way:

  • (CompanyName) User.java - a class that means User in the system

  • Profile.java . Class that stands for ROLE on the system in NN with (CompanyName) User . With ROLE, I mean a user group such as (ADMIN, ANONYMOUS, CUSTOMER SERVICE USER, etc.)

  • UserProfile.java . A class that denotes the relationship between User and Profile . It represents the JOIN TABLE for the NN relationship in the database.

  • Module.java . A class that stands for MODULE in a web application. Each module consists of unlimited functions, but all functions can only be associated with one MODULE . For example, the USER AUTHENTICATION function will be associated with the SECURITY or AUTHENTICATION module . Modules are controllers in the application, marked with @Controller.

  • Feature.java . The class that represents FEATURE in the application. Each function consists of one or more operations. For example, USER MANAGEMENT - CHARACTERISTIC. And as such, it is made up of many operations (like CREATE, READ, UPDATE and DELETE USER). Additionally, FEATURE has a login url that represents the url of that function (to redirect the user to that function when a button / link is clicked). Each url maps to a method in a module (controller).

  • Operation.java . A class that represents OPERATION in a web application. The operation is basically a single / basic operation like USER REGISTER or DELETE USER , but not necessarily a CRUD operation. Each operation has an ENTRY URL (the URL that shows the page to start the operation). For example, for a REGISTER USER operation, the URL entry would be / webapplicationName / moduleName (USER) / featureName / operationName (REGISTER USER) . But the operation may require a page flow. For example, for the operation USER REGISTRATIONProbably need a page with the registration form, URL-address (usually displayed for the method) as the action to send the form and SUCCESS / FAILURE to display the message SUCCESS / the ERROR .

  • Permission.java . A class that represents a URL on the system. Each permission is associated with 1 or many OPERATIONS (Operation.java) to create a PAGE FLOW . For example: the operation USER REGISTER will probably have the following URLs / PERMISSIONS :

    • / webapplicationName / moduleName (USER) / featureName (USER MANAGEMENT) / operationName (USER REGISTRATION) / register - URL mapped to a method in controller (CompanyNameUser) to submit the form (form action) and persist in the database normally calling DAO (CompanyNameUser) DAO

    • / webapplicationName / moduleName (USER) / featureName (USER CONTROL) / operationName (REGISTER USER) / success / - URL mapped to method in controller to show SUCCESS message

    • / webapplicationName / moduleName (USER) / featureName (USER CONTROL) / operationName (REGISTER USER) / error / - URL mapped to method in controller to show error message

  • ProfilePermission.java is a class representing the JOIN TABLE for the NN relationship between profiles and permissions.

The problem is that if I use Spring Security to implement access control, I am doomed to implement the User.java class (I cannot customize the name), also I need a class for ROLES and others for POWER, So I cannot create my own thread access control. I thought about using the SERVLET FILTER to test access / deny access. However, when I try to redirect the url or just execute chain.doFilter () inside my filter, it just shows ERROR 404. I think this is because I am using DefaultAnnotationHandlerMapping to handle requests. However, my configuration is this:

web.xml:

<?xml version="1.0" encoding="UTF-8"?>

<web-app version="2.5" 
   xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee     http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">`<display-name>cheapig</display-name>

<!-- ROOT CONTEXT DEFINITIONS -->
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>/WEB-INF/spring/root-context.xml</param-value>
</context-param>`
<listener>
    <listener-  class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener> 

<!-- The filter to implement my access control -->
<filter>
    <filter-name>securityFilter</filter-name>
    <filter-class>org.cheapig.security.SecurityFilter</filter-class>
</filter>

<filter-mapping>
  <filter-name>securityFilter</filter-name>
  <url-pattern>/**</url-pattern>
</filter-mapping>   

<servlet>
    <servlet-name>cheapig</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-   class>     <init-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>/WEB-INF/spring/cheapig/servlet-context.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
</servlet>  

<servlet-mapping>
    <servlet-name>cheapig</servlet-name>
    <url-pattern>/</url-pattern>
</servlet-mapping></web-app>

      

root context.xml:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:aop="http://www.springframework.org/schema/aop"       
xmlns:tx="http://www.springframework.org/schema/tx" 
xmlns:context="http://www.springframework.org/schema/context"       
xsi:schemaLocation="http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context
    http://www.springframework.org/schema/context/spring-context-3.1.xsd
    http://www.springframework.org/schema/tx
    http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
    http://www.springframework.org/schema/aop       
    http://www.springframework.org/schema/aop/spring-aop-3.1.xsd">
<!-- Root Context: defines shared resources visible to all other web components -->

<bean id="messageSource" class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
    <property name="basename" value="classpath:messages" />
    <property name="defaultEncoding" value="latin1"/>              
</bean>

<bean id="localeChangeInterceptor"
    class="org.springframework.web.servlet.i18n.LocaleChangeInterceptor">
    <property name="paramName" value="lang" />      
</bean>

<bean id="localeResolver"
    class="org.springframework.web.servlet.i18n.CookieLocaleResolver">
    <property name="defaultLocale" value="pt"/>

</bean>

<bean id="handlerMapping"
    class="org.springframework.web.servlet.mvc.annotation.DefaultAnnotationHandlerMapping">
   <property name="interceptors">
       <ref bean="localeChangeInterceptor" />
   </property>     
</bean></beans>

      

servlet context:

    <?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:context="http://www.springframework.org/schema/context"
xsi:schemaLocation="http://www.springframework.org/schema/mvc    http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd
    http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
    http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd">

    <!-- DispatcherServlet Context: defines this servlet request-processing   infrastructure -->

    <!-- Enables the Spring MVC @Controller programming model -->
    <annotation-driven />

    <!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
    <resources mapping="/resources/**" location="/resources/" />

    <!-- Imports user-defined @Controller beans that process client requests -->
    <beans:import resource="controllers.xml" />
    <beans:import resource="hibernateMySQL5.xml"/>      
    <context:component-scan base-package="br.com.cheapig" />
</beans:beans>

      

SecurityFilter.java:

package br.com.cheapig.security;

import java.io.IOException;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;

public class SecurityFilter implements Filter {

@Override
public void init(FilterConfig filterConfig) throws ServletException {
    // TODO Auto-generated method stub

}

@Override
public void doFilter(ServletRequest request, ServletResponse response,
        FilterChain chain) throws IOException, ServletException {

    // TODO Auto-generated method stub
    chain.doFilter(request, response);
}

@Override
public void destroy() {
    // TODO Auto-generated method stub
}
 }

      

So what should I do? Should I be using Spring Security? Is there a way to implement my own process with Spring Security? Should I use an interceptor in the handler mapping instead of using a filter? I would appreciate any help / suggestions.

Thanks in advance!

+3


source to share


2 answers


Have a look at Apache Shiro . It may better suit your requirements.



+2


source


This is a very late answer, but here for future generations.

I agree with sourcedelica that Apache Shiro is a good place to browse. However, I would also recommend that you take a step back and look at the theory behind your problem. Basically you are trying to implement this role-based access control model with users, groups, roles and permissions. Also, from reading your question, it appears that you have a relationship between the users requesting access and the target resources.

With this in mind, you need ABAC - Attribute Based Access Control - as defined by NIST in its report released earlier in 2014. You can read the report here .

With ABAC, you can describe your users in terms of attributes - any attribute - such as role, location, age, citizenship ... Similarly, you can describe resources and objects in this way, as well as the actions taken and the context.

This means that with attributes and ABAC, you can easily implement the following authorization requirements:

  • a user with role == editor can perform the action == edit resources of type == document if and only if the user is in the same department as the resources (user.department == resource.department)
  • a user can perform an == delete action on a resource of type == document if and only if the user owns the document (user.id == document.owner.id) and if the status is == draft.


To implement ABAC use XACML . XACML is an extensible access markup language defined by OASIS. It provides you with:

  • request / response scheme (how to ask questions and make decisions back),
  • political language (based on attributes of course) and
  • Architecture.

XACML Architecture

Google. There are many XACML resources for Java.

The benefits of using ABAC and XACML are that you end up disconnecting access control from your business logic, which means you can change your application regardless of your authorization logic and vice versa.

NTN

0


source







All Articles