最近我正在努力学习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
还有其他方式吗?如何在一个有很多角色,控制器等的大系统中完成。
答案 0 :(得分:2)
通常在Spring应用程序中,您有一个调度程序servlet。我不认为有一个用于公开请求,一个用于管理员请求购买任何东西。
是的,听起来不错
同样,我没有看到如何将管理员和公共JSP分成不同的目录来帮助你。如果您拥有两个区域共有的JSP
这取决于您的个人喜好。我用XML定义了我的安全性东西,但很多人更喜欢注释
答案 1 :(得分:2)
我知道我迟到了这个讨论(你现在可能已经解决了你的问题),但这里适合像我这样的所有后来者:)
使用Spring安全性(或任何安全框架),我们通常控制对应用程序“RESOURCES”(可通过应用程序URL访问)的访问,为此我们需要一个ROLE-TO-RESOURCE映射。
拥有2个不同的调度程序servlet并不是一个好方法,除非你有非常强烈的理由。要使用“Spring Security”,就足够了。
这是您应该开始的方法,允许基于用户ROLE访问URL模式。在允许访问所请求的URL之前,Spring安全框架类用于检查用户ROLE。
我们正在保护逻辑资源,我们无论如何都不允许用户直接访问我们的物理资源。将你的JSP保存在WEB-INF中,你就可以了。
您不需要为不同的ROLE使用不同的控制器。控制器方法用于提供Web请求,如果不允许用户访问特定URL,则不会执行为该URL提供服务的Controller方法。
答案 2 :(得分:1)
非常有趣的方法。您可以通过为每个调度程序servlet定义两个不同的控制器列表来解决您的实际问题。存档的方式有多种,例如:
OnlyForAdminController
和OnlyForPublicController
。注释相应的类。然后为每个调度程序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
管理员用户的情况下,用户可能会看到一些销售统计信息作为附加信息,其中公共用户可能会看到5个先前查看过的项目的列表。因此从性能的角度来看,您将拥有两个独立的控制器。在任何情况下,您都可以在可能的情况下重新启动某些控制器,并在以后请求某些特殊行为时为每个用户拆分这些控制器。当您在两种类型的用户之间只有很小的差异时,您的技术会更有趣。