Java 在Spring安全中使用截取url

Java 在Spring安全中使用截取url,java,spring,jakarta-ee,spring-security,Java,Spring,Jakarta Ee,Spring Security,在Spring security中,在拦截url元素中创建模式的首选方法是什么? 我正在创建一个web服务(RESTful),目前我要求所有用户都已登录并具有角色role\u USER。然后通过服务层上的@PreAuthorize注释强制执行进一步的约束。但是,添加多个具有不同配置的拦截url元素是否也很常见?SpringSecurity的配置取决于您为应用程序选择的身份验证: 例如,对于要在没有权限的情况下配置登录url和注销成功url的表单身份验证: <http realm="Cont

在Spring security中,在
拦截url
元素中创建模式的首选方法是什么?
我正在创建一个web服务(RESTful),目前我要求所有用户都已登录并具有角色
role\u USER
。然后通过服务层上的
@PreAuthorize
注释强制执行进一步的约束。但是,添加多个具有不同配置的
拦截url
元素是否也很常见?

SpringSecurity的配置取决于您为应用程序选择的身份验证: 例如,对于要在没有权限的情况下配置登录url和注销成功url的表单身份验证:

<http realm="Contacts Realm">
    <intercept-url pattern="/index.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    <intercept-url pattern="/login.jsp*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    <intercept-url pattern="/**" access="ROLE_USER"/>
    <form-login login-page="/login.jsp" authentication-failure-url="/login.jsp?login_error=1"/>
    <logout logout-success-url="/index.jsp"/>
</http>

对于基本身份验证,您没有登录和注销URL,配置更简单:

<http realm="Contacts Realm">
    <intercept-url pattern="/**" access="ROLE_USER"/>
    <http-basic/>
</http>


如果您将选择基本身份验证,请使用第二个示例。

Spring安全性通常适用于基于角色的访问。就这样。您可以创建自己的ProcessingFilter来执行一些其他操作。然而,我发现这是一个小利益的大量工作


另一种方法是使用请求拦截器。在几个使用springmvc的RESTful服务项目中,我使用请求拦截器来完成基本角色访问之外的一些身份验证。这是可行的,在我看来,这使得事件链更容易遵循,但是如果你每分钟处理数千个事务,它可能会使请求陷入困境。

拦截URL可以这样做。假设您的rest服务URL以
/rest/
开头

<http auto-config="true" use-expressions="true" access-denied-page="/accessDeniedPageURL">
    <intercept-url pattern="/rest/**" access="hasRole('ROLE_USER')"/>
    <intercept-url pattern="/view/products" access="isFullyAuthenticated()"/>        

    <form-login login-page="/landing" default-target-url="/view/products" authentication-failure-handler-ref="authenticationFailureHandler"/>
    <logout invalidate-session="true" logout-success-url="/landing" delete-cookies="JSESSIONID"/>

    <session-management invalid-session-url="/landing" session-authentication-error-url="/landing?msg=alreadyLogin">
        <concurrency-control max-sessions="1" expired-url="/landing?msg=sessionExpiredDuplicateLogin" error-if-maximum-exceeded="false"/>
    </session-management>    
</http>

大多数使用Spring Security的web应用程序只有几个
拦截url
,因为它们只有非常基本的安全要求。您需要对登录和登录错误屏幕以及公共站点的某些方面具有未经验证的访问权限,因此可以使用一些URL模式。然后通常会有一个管理部分,然后其他的都是
ROLE\u USER

如果需要更多的角色,通常会将它们与顶级URL路径组件相关联。虽然这不是必需的,但它使确保资源得到适当保护变得更容易


您必须根据您的用例决定是否允许人员担任多个角色。在应用程序中管理有点困难,因此大多数具有简单安全性的人都会设置它,以便用户只拥有一个角色,然后允许多个角色访问受保护的内容。当然,另一种方法是每个URL模式一个角色,并为人们提供多个角色

无论如何,对您的问题(或者至少是我认为您要问的问题)的答案是,通常要做的事情是每个角色一个顶级路径组件,以相同的安全限制保护所有资源。当然,您也在该路径前缀下对功能进行分组,因此有些人讨厌这种结构,有些人更喜欢在代码中使用注释。我喜欢我的安全性,我可以在一个地方看到它,并且通过查看URL就可以很容易地知道安全性期望是什么

我认为“首选方式”是主观的。我在
security.xml
中有
元素,但放弃了它们,转而使用控制器上带有
@PreAuthorize
@RequestMapping
注释。这纯粹是个人偏好(在我的例子中),因为我喜欢尽可能多地用Java而不是XML名称空间保存东西

您可以使用其中一种,也可以同时使用另一种,还可以使注释增强XML——例如,您可以使用如下内容:

security.xml

<intercept-url pattern="/something" access="hasRole('ROLE_USER')"/>
@RequestMapping(value="/something/else")
@PreAuthorize("hasRole('ROLE_ADMIN')")
public String getSomethingElseContents(){ return "somethingelse"; }
正如我所说,这似乎只是一个偏好的问题。使用XML名称空间的好处是基本访问规则都在一个地方,易于阅读,易于遵循。
@PreAuthorize
(或其他注释变体)强加的规则特别吸引人,因为您可以在其中调用自己的SpEL表达式,并根据对类传递的参数或可访问字段的访问来决定权限(即
@PreAuthorize(@my.project.package.hasMagicPower(#power.INVISIBILITY)
),或这些的组合。您可以应用逻辑和动态权限,这些权限在其他情况下对名称空间选项不可用

当然,您可以将基本逻辑应用于“and”、“or”和“!”命名空间中SpEL表达式中的连接符(您可以通过XML中的
@
指示符访问外部类[boolean]方法),但XML中指定的所有内容都必须是静态的


tl;dr:个人偏好是偏好,但如果您希望或需要权限处理的动态灵活性,则必须使用注释。如果您既不想要也不需要动态灵活性,那么您可以选择(并且一个合理的参数将表明相对于SoC,名称空间选项更好)。为了灵活性,我更喜欢让Java来处理它,因为一旦我设置了XML,我就想把它放在一边,专注于Java。此外,SoC视图还有一个令人信服的反驳,即一个适当常规化的Java应用程序将其控制器放在易于找到的包中,并具有明显的按名称控制



静止tl;dr:Meh。一个六个,另一个半打。我说po tay to.

是的,定义多个拦截url模式,然后在顶部添加注释以进一步限制特定资源是很常见的

您还可以为每个限制使用一个目录,这样您就不需要注释了。例如/user/**需要角色\用户,/admin/**需要角色\管理员,等等
<intercept-url pattern="/**" access="permitAll"/>
<intercept-url pattern="/user/**" access="hasRole('ROLE_USER')"/>
@PreAuthorize("hasRole('ROLE_USER')")