4

哥们,

我即将使用 Spring 3 MVC 作为 Web 框架,Hibernate Annotations 作为 ORM 框架来开发一个 Web 应用程序但是,我面临一个问题,为此应用程序设计一个基于数据库的良好访问控制。在我的工作中,我们习惯于这样设计:

  • (CompanyName)User.java - 表示系统中用户的类

  • Profile.java - 一个类,表示系统中的ROLE与(CompanyName)User有NN关系 。对于ROLE,我的意思是一个用户组,例如(ADMIN、ANONYMOUS、CUSTOMER SERVICE USER 等)

  • UserProfile.java - 表示UserProfile之间关系的类。它代表数据库中NN关系的JOIN TABLE 。

  • Module.java - 一个类,表示 Web 应用程序中的MODULE。每个模块由无限的特征组成,但每个特征只能与一个MODULE相关。例如,用户身份验证功能将与安全身份验证模块相关。模块是应用程序中使用@Controller 标记的控制器。

  • Feature.java - 表示应用程序中的FEATURE的类。每个功能都由一个或多个操作组成。例如,用户管理是一项功能。因此,它由许多操作组成(例如 CREATE、READ、UPDATE 和 DELETE USER)。此外,FEATURE 有一个 ENTRY URL,表示该功能的 URL(在单击按钮/链接时将用户重定向到该功能)。每个 URL 都映射到 Module(Controller) 中的一个方法。

  • Operation.java - 表示Web 应用程序中的操作的类。操作基本上是单个/基本操作,例如REGISTER USERREMOVE USER,但不一定是 CRUD 操作。每个操作都有一个ENTRY URL(显示开始操作的页面的 URL)。例如,对于USER REGISTRATION操作,条目URL将是/webapplicationName/moduleName(USER)/featureName(USER MANAGEMENT)/operationName(REGISTER USER)。但是一个操作可能需要一个页面流来完成。例如,用户注册操作可能需要一个带有注册表单的页面、一个 URL(通常映射到一个方法)作为提交表单的操作和一个SUCCESS/ERROR页面,以显示SUCCESS/ERROR消息。

  • Permission.java - 表示系统中URL的类。每个 Permission 都与一个或多个OPERATIONS (Operation.java) 相关,以组成一个PAGE FLOW。例如:一个USER REGISTRATION操作可能有以下URLs/PERMISSIONS

    • /webapplicationName/moduleName(USER)/featureName(USER MANAGEMENT)/operationName(USER REGISTRATION)/register - 映射到 (CompanyNameUser)Controller 中的方法的 URL,用于提交表单(表单操作)并保存在数据库中,通常调用(公司名称用户)DAO

    • /webapplicationName/moduleName(USER)/featureName(USER MANAGEMENT)/operationName(REGISTER USER)/success/ - 映射到控制器中的方法以显示成功消息的 URL

    • /webapplicationName/moduleName(USER)/featureName(USER MANAGEMENT)/operationName(REGISTER USER)/error/ - 映射到控制器中的方法以显示错误消息的 URL

  • ProfilePermission.java - 一个表示配置文件和权限之间的 NN 关系的 JOIN TABLE 的类。

这里的问题是,如果我使用 Spring Security 来实现访问控制,我注定要实现一个 User.java 类(我无法自定义名称),我还需要一个用于 ROLES 的类和其他用于 AUTHORITIES 的类。所以,我无法建立自己的访问控制流程。我想过使用 SERVLET FILTER 检查权限接受/拒绝访问。但是,当我尝试重定向到 URL 或仅在过滤器中执行 chain.doFilter() 时,它只会显示 ERROR 404。我认为这是因为我使用DefaultAnnotationHandlerMapping来处理请求。也就是说,我的配置如下:

网页.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>

根上下文.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 上下文:

    <?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's 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>

安全过滤器.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
}
 }

所以我该怎么做?我应该使用 Spring Security 吗?有什么方法可以使用 Spring Security 实现我自己的自定义流程?我应该在处理程序映射中使用拦截器而不是使用过滤器吗?我将不胜感激任何帮助/建议。

提前致谢!

4

2 回答 2

2

看看Apache Shiro。它可能更适合您的要求。

于 2012-04-01T17:47:33.783 回答
0

这是一个非常晚的回应,但这里适用于后代。

我同意sourcedelica的观点,即 Apache Shiro 是一个值得关注的好地方。但是,此外,我建议您退后一步,看看您的问题背后的理论。本质上,您尝试实现的是基于角色的访问控制模型,其中包含用户、组、角色和权限。此外,通过阅读您的问题,听起来您在请求访问的用户和目标资源之间存在关系。

考虑到这一点,您需要的是 NIST 在 2014 年初发布的报告中定义的 ABAC(基于属性的访问控制)。您可以在此处阅读报告

使用 ABAC,您可以根据属性 - 任何属性 - 例如角色、位置、年龄、公民身份来描述您的用户……类似地,您可以以这种方式描述资源和对象,以及尝试的操作和上下文。

这意味着使用属性和 ABAC,您可以轻松实现以下授权要求:

  • 当且仅当用户与资源在同一部门时,具有角色==编辑器的用户才能对类型==文档的资源执行操作==编辑(user.department==resource.department)
  • 当且仅当用户拥有文档 (user.id==document.owner.id) 并且状态==草稿时,用户才能对类型==文档的资源执行操作==删除。

要实现 ABAC,请继续使用XACML。XACML 是 OASIS 定义的可扩展访问控制标记语言。它为您提供:

  • 请求/响应方案(如何提出问题并收回决定),
  • 一种策略语言(当然是基于属性的),以及
  • 一种架构。

XACML 架构

谷歌周围。有大量用于 Java 的 XACML 资源。

使用 ABAC 和 XACML 的好处是您最终将访问控制与业务逻辑分离,这意味着您可以独立于授权逻辑更改应用程序,反之亦然。

高温高压

于 2014-11-19T13:59:52.427 回答