3

我正在开发一个使用 Spring MVC 和 Spring 安全性的 Java EE Web 应用程序。到目前为止,我成功地使用自定义 userService(它从我的数据库中检索信息)实现了常见的安全功能,但我现在面临一个新的安全问题,我真的不知道解决它的最佳方法是什么。 .

这是我需要做的:在我的应用程序中经过身份验证的用户可以浏览他们的项目,但应该只能打开他们有权访问的项目(并打开里面的内容),而不能打开其他项目。

我当前的实现处理它的导航(用户界面)只向用户提供授权项目的列表。但是,如果聪明的用户直接编辑 URL 以打开具有另一个 id 的项目,则不会对项目 id 进行授权测试,并且用户已完成,因此它可以毫无问题地打开项目。

所以,我想添加的是对打开项目或其中的某些内容的每个请求的控制。此控件将测试当前用户是否可以打开请求的项目 ID。如果没有,它将向用户返回拒绝访问页面。这个控件本身很容易实现,但由于它是一些代码,可能在我的应用程序的许多方法中,我想找到最干净的方法来做到这一点!

您认为实现它的最佳方法是什么?我考虑了几种可能性,但我需要建议:

1)使用servlet过滤器?

2) 使用自定义 authenticationManager 添加对 Spring 安全性的特殊访问?就像是 :

 <security:intercept-url pattern="/open*" access="canOpen()" /> 

(但我不确定如何定义它以及是否能够从原始请求中获取参数......)

3)使用面向方面的编程?(但我在某处读到它不适用于控制器调用)

4) 使用 Spring 拦截器?

5)其他想法?

提前感谢您的帮助!

4

2 回答 2

4

我建议您使用自定义 PermissionEvaluator 以便您基本上可以在网页和控制器中使用相同的实现:

在您可以使用的网页中:
<security:authorize access="hasPermission(#project,'read')"></security:authorize>

在您的控制器和您可以使用的任何服务方法中:
@PreAuthorize("hasPermission(#project,'read')")

或者也@PostAuthorize@PostFilter("hasPermission(filterObject,'read')")(对于列表)

所有这些功能将根据您自己的权限评估者限制访问或过滤结果列表。它们都将指向相同的实现,看起来像这样:

@Component
public class MyPermissionEvaluator implements PermissionEvaluator {

    private final Log logger = LogFactory.getLog(getClass());

    @Override
    public boolean hasPermission(Authentication auth, Object arg1, Object arg2) {
        logger.info("hasPermission "+auth+" - "+arg1+" - "+arg2+" ");
        if(arg2 instanceof String && arg1 instanceof MyProject){
            MyProject project = (MyProject)arg1;
            if(((String) arg2).equals("read")){
                boolean result = hasPermissionReadProject(auth, project);                   
                return result;
            }
        }
        return false;
    }

    @Override
    public boolean hasPermission(Authentication arg0, Serializable arg1,
        String arg2, Object arg3) {
        logger.info("hasPermission "+arg0+" - "+arg1+" - "+arg2+" - "+arg3+" ");
        return false;
    }
}

此外,当这些方法返回 false 时,它​​会自动抛出 AccessDeniedException,您可以轻松地将其配置为在 http 元素中重定向到您自己的 accessDenied 页面:

<http auto-config="true">
    <intercept-url pattern="/admin*" access="ROLE_ADMIN" />
    <access-denied-handler error-page="accessDeniedPage"/>
</http>
于 2012-11-20T16:17:23.313 回答
0

我没有使用 Spring Security,但我不得不面对类似的情况。

我选择实现数据库访问验证。我的每个请求都有一个内置的用户/数据确认。也许这不是最简单的方法,但是这样,用户只能请求他们可以读/写的数据。我从来没有遇到过任何麻烦。

我的请求适用于登录用户角色。例如,在我的例子中,如果用户是学生,他只能访问自己的文件夹,但如果是老师,他可以访问他教给的学生的文件夹。

请求(简化​​了很多!)[使用 IBatis]:

SELECT * 
    FROM FOLDER F 
    <dynamic prepend="WHERE">
        <isNotEmpty property="user">
            <isEqual property="user.role" compareValue="student">
                F.ID_STUDENT = #user.idStudent:NUMERIC#
            </isEqual>
            <isEqual property="user.role" compareValue="teacher">
                F.ID_STUDENT IN 
                    (SELECT ID_STUDENT 
                        FROM CLASSES 
                    WHERE ID_TEACHER = #user.id:NUMERIC#)
            </isNotEmpty>
        </isNotEmpty>
        <isEmpty property="user">
            F.ID IS NULL
        </isEmpty>
    </dynamic>
于 2012-11-20T16:18:44.610 回答