Spring MVC - Spring Security - 控制器通用架构 - 最佳实践

时间:2013-05-05 20:56:03

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

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

  • 客户
  • 管理

您可以将该应用视为经典的购物网络应用,其中管理员可以添加新商品,客户可以查看列出的商品并添加到购物车中。 我的问题现在是关于系统的通用架构,它应该是Spring Framework的最佳实践示例之一。

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

1 - 我有2个不同的调度程序servlet。因此,公开的网址将面向客户,管理员将面向管理员。

<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中,我对admin进行了身份验证,如下所示:

<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等。对于每个域对象,我有一个Controller类,即ItemController,它处理有关项目的整个请求(客户和管理员)

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

当我逐一思考这些决定时,每一个决定都是有意义的。但实际上,很明显,因为我没有看到任何大的Spring应用程序(互联网包含许多小代码部分,而不是对整体有所了解),这里有一些错误。

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

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

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

OR

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

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

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

OR

还有其他方式吗?如何在一个有很多角色,控制器等的大系统中完成。

3 个答案:

答案 0 :(得分:2)

  1. 通常在Spring应用程序中,您有一个调度程序servlet。我不认为有一个用于公开请求,一个用于管理员请求购买任何东西。

  2. 是的,听起来不错

  3. 同样,我没有看到如何将管理员和公共JSP分成不同的目录来帮助你。如果您拥有两个区域共有的JSP

  4. ,最终可能会让您感到困惑
  5. 这取决于您的个人喜好。我用XML定义了我的安全性东西,但很多人更喜欢注释

答案 1 :(得分:2)

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

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

  1. 拥有2个不同的调度程序servlet并不是一个好方法,除非你有非常强烈的理由。要使用“Spring Security”,就足够了。

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

  3. 我们正在保护逻辑资源,我们无论如何都不允许用户直接访问我们的物理资源。将你的JSP保存在WEB-INF中,你就可以了。

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

答案 2 :(得分:1)

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

  1. 而不是使用组件扫描以XML格式手动声明每个控制器。
  2. 如果您没有例外,则可以使用filters。创建两个新注释OnlyForAdminControllerOnlyForPublicController。注释相应的类。然后为每个调度程序servlet自定义组件扫描选项:
  3. <!-- 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管理员用户的情况下,用户可能会看到一些销售统计信息作为附加信息,其中公共用户可能会看到5个先前查看过的项目的列表。因此从性能的角度来看,您将拥有两个独立的控制器。在任何情况下,您都可以在可能的情况下重新启动某些控制器,并在以后请求某些特殊行为时为每个用户拆分这些控制器。当您在两种类型的用户之间只有很小的差异时,您的技术会更有趣。