【问题标题】:Spring MVC - Spring Security - Controllers General Architecture - Best practicesSpring MVC - Spring Security - 控制器通用架构 - 最佳实践
【发布时间】:2013-04-29 15:16:39
【问题描述】:

最近我正在尝试学习 Spring。我创建了一个简单的 webapp,它基本上应该有两种类型的用户:

  • 客户
  • 管理员

您可以将应用程序想象成一个经典的购物网络应用程序,管理员有权添加新商品,客户可以查看列出的商品并将其添加到他们的购物车中。 我现在的问题是关于系统的一般架构,这应该是 Spring Framework 的最佳实践示例之一。

我可以在这里列出有关此架构决策的要点,您可以告诉我您是否会以其他方式进行:

1- 我有 2 个不同的调度程序 servlet。因此,public 下的 url 将用于客户,而 admin 将用于管理员。

<servlet-mapping>
    <servlet-name>public-dispatcher</servlet-name>
    <url-pattern>/public/*</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>admin-dispatcher</servlet-name>
    <url-pattern>/admin/*</url-pattern>
</servlet-mapping>

2- 在 Spring-Security.xml 我有这样的管理员身份验证:

<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />

(url /admin/ 下的所有操作都将受密码保护)

3-每个Servlet都有一个viewResolver指向不同的文件夹,里面包含jsps:

/WEB-INF/admin-jsp/  (admin jsps)
/WEB-INF/public-jsp/  (customer jsps)

4- 假设我有这些域对象:Item、ShoppingCart、Customer 等。对于每个域对象,我都有一个控制器类,即 ItemController,它处理关于一个项目的整个请求(客户和管理员) .

@Controller
@RequestMapping("/item")
@SessionAttributes({"cart"})
public class ItemController { ...

当我一一考虑时,这些决定中的每一个都是有意义的。但实际上,很明显,由于我没有看到任何大型 Spring 应用程序(互联网包含许多小代码部分,无法了解整体),所以这里有问题..

例如:我可以将此 url 称为客户 /public/item/addNewItem(实际上是为管理员提供的),并且该方法将被执行,因为 ItemController (/item) 对每个人都是可见的。但是由于我在 2 个不同的位置有 jsps,所以 spring 会抛出 View 不存在的错误。 同样作为管理员,当我可以调用 url /admin/item/addToCart....

什么是最好的拱门。实施整体?我应该在安全配置中定义更多的 url 吗?例如:

<intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
<intercept-url pattern="/admin/addNewItem" access="ROLE_ADMIN" />

我应该为不同的角色定义不同的控制器吗?

 @RequestMapping("/public/item")
    @SessionAttributes({"cart"})
    public class PublicItemController { ...

 @RequestMapping("/admin/item")
    public class AdminItemController { ...

还有什么办法吗?在一个有很多角色、控制器等发生的大系统中应该如何完成。

【问题讨论】:

    标签: spring spring-mvc architecture controller spring-security


    【解决方案1】:

    我知道我迟到了这个讨论(你现在可能已经解决了你的问题),但这里是为所有像我这样的迟到者准备的 :)

    使用 Spring 安全性(或任何安全性框架),我们通常控制对应用程序“资源”(可通过​​应用程序 URL 访问)的访问,为此我们需要 ROLE-TO-RESOURCE 映射。

    1. 拥有 2 个不同的调度程序 servlet 不是一个好方法,除非您有充分的理由。而使用“Spring Security”,一个就够了。

    2. 这是您应该开始使用的方法,允许基于用户角色访问 URL 模式。 Spring 安全框架类用于在允许访问请求的 URL 之前检查用户角色。

    3. 我们正在保护逻辑资源,无论如何我们不允许用户直接访问我们的物理资源。将您的 JSP 保存在 WEB-INF 中,一切顺利。

    4. 您不需要为不同的角色使用不同的控制器。控制器方法用于处理 Web 请求,如果不允许用户访问特定 URL,则为该 URL 提供服务的控制器方法将永远不会被执行。

    【讨论】:

      【解决方案2】:
      1. 通常在 Spring 应用程序中,您有一个调度程序 servlet。我不认为有一个用于公共请求和一个用于管理员请求可以为您带来任何好处。

      2. 是的,听起来不错

      3. 再一次,我看不出将管理和公共 JSP 拆分到单独的目录对您有什么帮助。如果您拥有两个领域共有的 JSP,最终可能会让您感到困惑

      4. 这取决于您的个人喜好。我用 XML 定义我的安全性内容,但很多人更喜欢注释

      【讨论】:

      • 谢谢。 4. point实际上更多的是关于Controller Class count pro Domain Object,而不是基于Annotation的配置;)
      • 啊,好的。在那种情况下,我可能会为管理员和公共项目控制器设置单独的控制器。
      【解决方案3】:

      非常有趣的方法。您可以通过为每个调度程序 servlet 定义两个不同的控制器列表来解决您的实际问题。有多种存档方式,例如:

      1. 不是使用组件扫描,而是在 XML 中手动声明每个控制器。
      2. 如果您有几个例外,那么您可以使用filters。创建两个新注释,OnlyForAdminControllerOnlyForPublicController。注释相应的类。然后为每个调度程序 servlet 自定义组件扫描选项:
      <!-- For public  -->
      <context:component-scan base-package="com.yourproject.conrollers">
          <context:exclude-filter type="annotation" expression="com.yourproject.annotation.OnlyForAdminController"/>
      </context:component-scan>
      
      
      <!-- For admin  -->
      <context:component-scan base-package="com.yourproject.conrollers">
          <context:exclude-filter type="annotation" expression="com.yourproject.annotation.OnlyForPublicController"/>
      </context:component-scan>
      

      在这种类型的实际系统(电子商店)中,大多数时候您会对公共和管理员用户有一些特殊要求。例如,在ItemController admin 用户可能会看到一些销售统计信息作为附加信息的情况下,公共用户可能会看到 5 个以前查看过的项目的列表。因此,从性能的角度来看,您将拥有两个独立的控制器。在任何情况下,您都可以在可能的情况下开始重用一些控制器,并在以后请求某些特殊行为时将这些控制器拆分为每个用户。当两种类型的用户之间只有微小的差异时,您的技术会更有趣。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2010-11-07
        • 2015-09-11
        • 2014-06-26
        • 2015-04-19
        • 2011-05-18
        • 1970-01-01
        • 2018-04-24
        • 1970-01-01
        相关资源
        最近更新 更多