簡體   English   中英

使用Grails Spring Security自動登錄

[英]login automatically with Grails Spring Security

我的Grails應用程序正在使用Spring Security插件。 我需要以編程方式登錄用戶,而且我無法訪問他們的密碼。 我嘗試了以下,當使用Acegi插件(Spring Security插件的祖先)時,它應該有效:

// automatically login a user and assign them the USER role. 
// In my app, the email address is also the username
GrantedAuthority[] auths = [new GrantedAuthorityImpl('USER')]
SecurityContextHolder.context.authentication 
        = new UsernamePasswordAuthenticationToken(email, 'unknown', auths)

看起來這幾乎有效,因為如果我在執行上述springSecurityService.principal后調用springSecurityService.principal返回自動登錄用戶的電子郵件地址。 但是,如果我調用springSecurityService.currentUser我會收到錯誤。 此錯誤的根本原因是:

SpringSecurityUtils.securityConfig.userLookup.userDomainClassName

返回“Person”,它不是我的用戶類的名稱。 諸如<sec:loggedInUser>類的各種標簽也不起作用,大概是出於同樣的原因。

我想知道這個問題是否與我使用預先存在的用戶和角色域類 (而不是插件生成的類)的事實有關? 如果用戶通過在表單中​​輸入用戶名和密碼(而不是以編程方式)登錄,則一切似乎都能正常工作。

更新

按照Burt的建議 ,我將上面的代碼替換為:

springSecurityService.reauthenticate(email)

但我仍然在SpringSecurityService.getCurrentUser()這些行上出錯

String className = SpringSecurityUtils.securityConfig.userLookup.userDomainClassName
grailsApplication.getClassForName(className).get(principal.id)

因為className設置為“Person”,而不是我的User類的名稱。

如果用戶在數據庫中使用存在springSecurityService.reauthenticate() -看到這個鏈接或Grails的2 此鏈接 Grails的3。

此方法旨在在用戶更改使其與數據庫不同步時更新身份驗證,但對於您希望強制對現有用戶進行有效身份驗證但不知道密碼的情況也很有用。

reauthenticate()方法有兩個限制:

  • 它不檢查密碼
  • 它不會引發事件。 這就是為什么許多監聽事件的插件可能無法正常工作的原因。 例如蠻力防御者插件。

也許這個代碼來自我寫的webapp的snippit會有所幫助。 我們必須使用RESTful API授權用戶,並且他們提供了用戶名和API密鑰。此代碼中的關鍵部分是設置權限和經過身份驗證的布爾值。

class CustomAppTokenAuthenticationProvider implements AuthenticationProvider {

  def userDetailsService

  Authentication authenticate(Authentication customAuth) {
    def userDetails = userDetailsService.loadUserByUsername(customAuth.principal)
    def user = User.get(userDetails.id)
    if (user?.apiKey.equals(customAuth.credentials)) {
      customAuth.authorities = userDetails.authorities
      customAuth.authenticated = true
      return customAuth
    } else {
      return customAuth
    }
  }

  boolean supports(Class authentication) {
    return CustomAppTokenAuthentication.class.isAssignableFrom(authentication)
  }
}

以下是來自過濾器的代碼,用於攔截API調用以處理身份驗證

    def userId = request.getHeader("x-user-external-id")
    def apiKey = request.getHeader("x-user-api-key")
    if (userId && apiKey) {
      def user = User.findByExternalId(userId)

      def myAuth = new CustomAppTokenAuthentication(
              name: userId,
              credentials: apiKey,
              principal: user.username,
              authenticated: false
      )

      def auth = authenticationManager.authenticate(myAuth);
      if (auth?.authorities?.size() >= 0) {
        log.info "Successfully Authenticated ${userId} in object ${auth}"
        // Store to SecurityContextHolder
        SecurityContextHolder.getContext().setAuthentication(myAuth);
      } else {
        SecurityContextHolder.getContext().setAuthentication(null)
      }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM