1

我一直在寻找一个具体、严肃和完整的示例,说明如何在 Spring Boot 应用程序中使用 Spring 安全性,该应用程序使用Spring 数据存储库访问数据库并因此查询注册用户。

我已经看到,通过覆盖该方法,它可以使用 Spring 安全性轻松保护一系列网页configure,例如使用以下选项:

http.authorizeRequests()
    .antMatchers("/", "/css/**", "/js/**", "/vendor/**", "/templates/**")
    .permitAll()
    .anyRequest()
    .authenticated()
    .and()
    .formLogin()
    .loginPage("/login")
    .permitAll()
    .and()
    .logout()
    .permitAll();

例如,此代码保护用户免于访问http://localhost:3000/home/users/,但允许然后访问http://localhost:3000/login或简单地访问http://localhost:3000

我一直在阅读有关 Spring 安全性的信息,但我不知道如何保护应用程序的不同部分,例如,当用户登录网站时,并禁止他从 examplehttp://localhost:3000/home/users/another_user和一般用于控制登录用户对网站所有部分的访问。

我正在使用Spring 数据存储库通过实体来操作数据库的数据。

您是否知道将 Spring 安全性与 Spring 存储库(以及必要时的其他工具)结合使用来保护(和验证)网站不同部分的示例?(视频)教程也可能有用。

谢谢你的帮助。

注意:我查看了 sagan 网站的存储库,但要理解发生了什么非常复杂......

4

2 回答 2

2

如上所述,ACL 是一种选择,但另一种可能更简单的解决方案可能是在方法级别应用安全性。

请参阅第 15.3 节。

https://docs.spring.io/spring-security/site/docs/3.0.x/reference/el-access.html

因此,假设您有一个 URL /users/123,其中 123 是当前用户,它委托给服务层方法来加载用户,那么我该如何防止用户篡改 URL 并查看 /users/456 等返回的数据.

一种方法是通过 @PostAuthorize 注释应用方法级别的安全性:

@PostAuthorize("hasPermission(returnObject, null)")
public User findById(Long id) {
    return repository.findOne(id);
}

安全检查委托给 org.springframework.security.access.PermissionEvaluator 的实现

一个实现可能如下所示:

public class BasePermissionsEvaluator implements PermissionEvaluator {

    public boolean hasPermission(Authentication authentication, Object domainObject) {
        return hasPermission(authentication, domainObject, null);
    }

    @Override
    public boolean hasPermission(Authentication authentication, Object domainObject, Object permission) {
        boolean hasPermission = true;

        //User is my custom class representing a logged in user
        //UserEntity is my custom interface implemented by entities associated with specific user
        //If user is an Admin allow access
        //Otherwise allow access if logged in user 'owns' the DomainObject instance
        User user = (User) authentication.getPrincipal();

        if(! user.isAdmin()){
            if (domainObject instanceof UserEntity) {
                User owner = ((UserEntity) domainObject).getOwner();
                hasPermission = user.equals(owner);
            }
        }

        return hasPermission;
    }

    @Override
    public boolean hasPermission(Authentication authentication, Serializable targetId, String targetType,
            Object permission) {
        return false;
    }
}

PermissionEvaluator 的配置在 XML 中如下所示,因此您需要转换为 Java 配置:

<security:global-method-security
    pre-post-annotations="enabled">
        <security:expression-handler ref="expressionHandler"/>
</security:global-method-security>

<bean id="expressionHandler"
    class="org.springframework.security.access.expression.method.DefaultMethodSecurityExpressionHandler">
    <property name="permissionEvaluator" ref="permissionEvaluator" />
</bean>

<bean id="permissionEvaluator" class="com.mycompany.BasePermissionsEvaluator" />

以下概述了将 XML 配置转换为 Java 配置:

https://spring.io/blog/2013/07/04/spring-security-java-config-preview-method-security/#custom-method-security

因此,在您现有的安全配置类中,您似乎会添加:

@EnableGlobalMethodSecurity(prePostEnabled=true) //ADD THIS
public class MySecurityConfig{

  @Override
  protected MethodSecurityExpressionHandler expressionHandler() {
    DefaultMethodSecurityExpressionHandler expressionHandler = new DefaultMethodSecurityExpressionHandler();

    //SET TO OUR CUSTOM PERMISSIONS HANDLER DETAILED ABOVE
    expressionHandler.setPermissionEvaluator(new BasePermissionsEvaluator());

    return expressionHandler;
  }
}
于 2016-05-05T21:16:14.273 回答
1

这称为访问控制,或 Spring Security 中的“域对象安全”。

http://docs.spring.io/spring-security/site/docs/current/reference/htmlsingle/#domain-acls

你有很多阅读要做!

您可能希望将它与 Spring Data JPA 结合使用,以便 SDJ 只返回它应该返回的记录。这里有一个例子:

https://github.com/spring-projects/spring-data-examples/tree/master/jpa/security

基本上,您将向表中添加一些“行所有者”信息,并让 SDJ 和 SS 一起工作以控制访问,例如:

@Query("select o from BusinessObject o where o.owner.emailAddress like ?#{hasRole('ROLE_ADMIN') ? '%' : principal.emailAddress}")
List<BusinessObject> findBusinessObjectsForCurrentUser();

另一种方法是使用支持行安全的数据库服务器,如 PostgreSQL,并在数据库中处理您的访问控制权。

于 2016-05-05T20:03:18.137 回答