【问题标题】:Null springSecurityService causes encodePassword to fail in Grails 2.0.1Null springSecurityService 导致 encodePassword 在 Grails 2.0.1 中失败
【发布时间】:2012-03-31 15:46:01
【问题描述】:

我们正在使用 Grails 2.0.1 和 Spring Security 开发一个新项目。由于用户域对象中的 springSecurityService 为空,创建用户上下文失败。奇怪的是,这仅发生在我们的 Linux 文本框上,而在所有开发人员的 windows 框上都可以正常工作。不确定它是否与环境有关,或者是否是其他原因。在 linux 机器上,这始终失败。

我们正在使用的用户域类如下(插件生成的类带有几个附加字段)。 encodePassword 由 beforeInsert()、beforeUpdate() 触发器处理。

遇到了这个线程,它讨论了导致 webflows 问题的瞬态引用,我认为这里没有使用它,所以不确定这是否相关。 http://grails.1312388.n4.nabble.com/Spring-Security-Plugin-1-of-the-time-springSecurityService-null-td4349941.html

class User {

    transient springSecurityService

    static constraints = {
        firstName blank: false, nullable: false, size: 2..100
        lastName blank: false, nullable: false, size: 2..100
        username blank: false, nullable: false, unique : true, email: true
        password blank: false, nullable: false, size: 6..255
    }

    static mapping = {
        password column: '`password`'
    }

    String username
    String password
    boolean enabled
    boolean accountExpired
    boolean accountLocked
    boolean passwordExpired

    /* user details */
    String firstName;
    String lastName;

    Set<Role> getAuthorities() {
        UserRole.findAllByUser(this).collect { it.role } as Set
    }

    def beforeInsert() {
        encodePassword()
    }

    def beforeUpdate() {
        if (isDirty('password')) {
            encodePassword()
        }
    }

    protected void encodePassword() {
        password = springSecurityService.encodePassword(password)
    }
}

提前致谢

【问题讨论】:

  • 我不希望在用户域中使用 encodePassword,而是在创建用户时使用:控制器,服务,测试:新用户(用户名:“root”,密码:springSecurityService.encodePassword('1 ')) 我不认为这是解决方法或黑客攻击。
  • 那么有一些方法可以创建一个新的用户实例,而无需对其密码进行编码,因为调用者确实不一定必须使用 encodePassword。此设计决策确保在操作用户域时始终对密码进行编码,从安全角度来看,这更加健壮。

标签: grails spring-security


【解决方案1】:

我知道测试注入用户域类的 SpringSecurity 服务存在一些问题。看看这个问题:How to test unit test controllers that use SpringSecurity service

【讨论】:

    【解决方案2】:

    springSecurityService 不能是瞬态的。以下代码应该可以工作

    class User {
    
      def springSecurityService
    
      static transients = ["springSecurityService"]
    
      protected void encodePassword() {
          password = springSecurityService.encodePassword(password)
      }
    }
    

    【讨论】:

      【解决方案3】:

      如果您只想确保保存 User 对象并且不关心测试的密码,则可以使用 Groovy 的元编程来覆盖 encodePassword 方法。

      @TestFor(UserService)    
      @Mock(User)
      class UserServiceTest {
          void testMethod() {
              User.metaClass.encodePassword = { -> }
      
              service.invokeTestThatSavesUserDomainClass()
          }   
      }
      

      【讨论】:

      • 快照很简单。正是我正在寻找的新的测试和所有。我阅读了关于这个问题的其他解决方案和其他关于同一问题的 SO 帖子,这是迄今为止最简单的解决方案!
      猜你喜欢
      • 1970-01-01
      • 2015-12-08
      • 2023-03-25
      • 1970-01-01
      • 2017-08-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多