1

Я использую grails 2.1.0. Я установил плагин весенне-защитного ядра.grails spring security login не работает

Когда я создаю пользователя, он его создает. Но когда я пытаюсь войти в системе, то это показывает:

"Sorry, we were not able to find a user with that username and password."

И есть еще один факт, что, когда я использую один и тот же пароль для другого пользователя, он не сохраняет пароль с аналогичным закодированным значением, как для пользователя 1 I использовал пароль 123, который сохраняется в базе данных, как этот

d535ce213a0e8e4f9e724af47c46eea409ef401c03617b749da618a82890d743

и для пользователя 2 Я также использовал пароль 123 и на этот раз он будет сохранен как этот

0849ea79a2c1bca057ded06c3053fb5bc5d7ba52b50982e73e44894d4f3e0aa6

Я не понимаю. Может ли кто-нибудь помочь мне в этом?

мой Config.groovy >>>

// locations to search for config files that get merged into the main config; 
// config files can be ConfigSlurper scripts, Java properties files, or classes 
// in the classpath in ConfigSlurper format 

// grails.config.locations = [ "classpath:${appName}-config.properties", 
//        "classpath:${appName}-config.groovy", 
//        "file:${userHome}/.grails/${appName}-config.properties", 
//        "file:${userHome}/.grails/${appName}-config.groovy"] 

// if (System.properties["${appName}.config.location"]) { 
// grails.config.locations << "file:" + System.properties["${appName}.config.location"] 
// } 

grails.project.groupId = appName // change this to alter the default package name and Maven publishing destination 
grails.mime.file.extensions = true // enables the parsing of file extensions from URLs into the request format 
grails.mime.use.accept.header = false 
grails.mime.types = [ 
    all:   '*/*', 
    atom:   'application/atom+xml', 
    css:   'text/css', 
    csv:   'text/csv', 
    form:   'application/x-www-form-urlencoded', 
    html:   ['text/html','application/xhtml+xml'], 
    js:   'text/javascript', 
    json:   ['application/json', 'text/json'], 
    multipartForm: 'multipart/form-data', 
    rss:   'application/rss+xml', 
    text:   'text/plain', 
    xml:   ['text/xml', 'application/xml'] 
] 

// URL Mapping Cache Max Size, defaults to 5000 
//grails.urlmapping.cache.maxsize = 1000 

// What URL patterns should be processed by the resources plugin 
grails.resources.adhoc.patterns = ['/images/*', '/css/*', '/js/*', '/plugins/*'] 

// The default codec used to encode data with ${} 
grails.views.default.codec = "none" // none, html, base64 
grails.views.gsp.encoding = "UTF-8" 
grails.converters.encoding = "UTF-8" 
// enable Sitemesh preprocessing of GSP pages 
grails.views.gsp.sitemesh.preprocess = true 
// scaffolding templates configuration 
grails.scaffolding.templates.domainSuffix = 'Instance' 

// Set to false to use the new Grails 1.2 JSONBuilder in the render method 
grails.json.legacy.builder = false 
// enabled native2ascii conversion of i18n properties files 
grails.enable.native2ascii = true 
// packages to include in Spring bean scanning 
grails.spring.bean.packages = [] 
// whether to disable processing of multi part requests 
grails.web.disable.multipart=false 

// request parameters to mask when logging exceptions 
grails.exceptionresolver.params.exclude = ['password'] 

// configure auto-caching of queries by default (if false you can cache individual queries with 'cache: true') 
grails.hibernate.cache.queries = false 

environments { 
    development { 
     grails.logging.jul.usebridge = true 
    } 
    production { 
     grails.logging.jul.usebridge = false 
     // TODO: grails.serverURL = "http://www.changeme.com" 
    } 
} 

// log4j configuration 
log4j = { 
    // Example of changing the log pattern for the default console appender: 
    // 
    //appenders { 
    // console name:'stdout', layout:pattern(conversionPattern: '%c{2} %m%n') 
    //} 

    error 'org.codehaus.groovy.grails.web.servlet',  // controllers 
      'org.codehaus.groovy.grails.web.pages',   // GSP 
      'org.codehaus.groovy.grails.web.sitemesh',  // layouts 
      'org.codehaus.groovy.grails.web.mapping.filter', // URL mapping 
      'org.codehaus.groovy.grails.web.mapping',  // URL mapping 
      'org.codehaus.groovy.grails.commons',   // core/classloading 
      'org.codehaus.groovy.grails.plugins',   // plugins 
      'org.codehaus.groovy.grails.orm.hibernate',  // hibernate integration 
      'org.springframework', 
      'org.hibernate', 
      'net.sf.ehcache.hibernate' 
} 

// Added by the Spring Security Core plugin: 
grails.plugins.springsecurity.userLookup.userDomainClassName = 'common.auth.User' 
grails.plugins.springsecurity.userLookup.authorityJoinClassName = 'common.auth.UserAuthority' 
grails.plugins.springsecurity.authority.className = 'common.auth.Authority' 

мой контроллер Войти >>>

import grails.converters.JSON 

import javax.servlet.http.HttpServletResponse 

import org.codehaus.groovy.grails.plugins.springsecurity.SpringSecurityUtils 

import org.springframework.security.authentication.AccountExpiredException 
import org.springframework.security.authentication.CredentialsExpiredException 
import org.springframework.security.authentication.DisabledException 
import org.springframework.security.authentication.LockedException 
import org.springframework.security.core.context.SecurityContextHolder as SCH 
import org.springframework.security.web.WebAttributes 
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter 

class LoginController { 

    /** 
    * Dependency injection for the authenticationTrustResolver. 
    */ 
    def authenticationTrustResolver 

    /** 
    * Dependency injection for the springSecurityService. 
    */ 
    def springSecurityService 

    /** 
    * Default action; redirects to 'defaultTargetUrl' if logged in, /login/auth otherwise. 
    */ 
    def index = { 
     if (springSecurityService.isLoggedIn()) { 
      redirect uri: SpringSecurityUtils.securityConfig.successHandler.defaultTargetUrl 
     } else { 
      redirect action: 'auth', params: params 
     } 
    } 

    /** 
    * Show the login page. 
    */ 
    def auth = { 

     def config = SpringSecurityUtils.securityConfig 

     if (springSecurityService.isLoggedIn()) { 
      redirect uri: config.successHandler.defaultTargetUrl 
      return 
     } 

     String view = 'auth' 
     String postUrl = "${request.contextPath}${config.apf.filterProcessesUrl}" 
     render view: view, model: [postUrl: postUrl, 
       rememberMeParameter: config.rememberMe.parameter] 
    } 

    /** 
    * The redirect action for Ajax requests. 
    */ 
    def authAjax = { 
     response.setHeader 'Location', SpringSecurityUtils.securityConfig.auth.ajaxLoginFormUrl 
     response.sendError HttpServletResponse.SC_UNAUTHORIZED 
    } 

    /** 
    * Show denied page. 
    */ 
    def denied = { 
     if (springSecurityService.isLoggedIn() && 
       authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) { 
      // have cookie but the page is guarded with IS_AUTHENTICATED_FULLY 
      redirect action: 'full', params: params 
     } 
    } 

    /** 
    * Login page for users with a remember-me cookie but accessing a IS_AUTHENTICATED_FULLY page. 
    */ 
    def full = { 
     def config = SpringSecurityUtils.securityConfig 
     render view: 'auth', params: params, 
       model: [hasCookie: authenticationTrustResolver.isRememberMe(SCH.context?.authentication), 
         postUrl: "${request.contextPath}${config.apf.filterProcessesUrl}"] 
    } 

    /** 
    * Callback after a failed login. Redirects to the auth page with a warning message. 
    */ 
    def authfail = { 

     def username = session[UsernamePasswordAuthenticationFilter.SPRING_SECURITY_LAST_USERNAME_KEY] 
     String msg = '' 
     def exception = session[WebAttributes.AUTHENTICATION_EXCEPTION] 
     if (exception) { 
      if (exception instanceof AccountExpiredException) { 
       msg = g.message(code: "springSecurity.errors.login.expired") 
      } else if (exception instanceof CredentialsExpiredException) { 
       msg = g.message(code: "springSecurity.errors.login.passwordExpired") 
      } else if (exception instanceof DisabledException) { 
       msg = g.message(code: "springSecurity.errors.login.disabled") 
      } else if (exception instanceof LockedException) { 
       msg = g.message(code: "springSecurity.errors.login.locked") 
      } else { 
       msg = g.message(code: "springSecurity.errors.login.fail") 
      } 
     } 

     if (springSecurityService.isAjax(request)) { 
      render([error: msg] as JSON) 
     } else { 
      flash.message = msg 
      redirect action: 'auth', params: params 
     } 
    } 

    /** 
    * The Ajax success redirect url. 
    */ 
    def ajaxSuccess = { 
     render([success: true, username: springSecurityService.authentication.name] as JSON) 
    } 

    /** 
    * The Ajax denied redirect url. 
    */ 
    def ajaxDenied = { 
     render([error: 'access denied'] as JSON) 
    } 
} 

мой authority.groovy >>>

package common.auth 

class Authority { 

    String authority 

    static mapping = { 
     cache true 
    } 

    static constraints = { 
     authority blank: false, unique: true 
    } 
} 

мой пользователь domain.groovy где мой пользователь будет сохранен >>>

package common.auth 

class User { 

    transient springSecurityService 
    String realname 
    String username 
    String password 
    String designation 
    boolean enabled 
    boolean accountExpired 
    boolean accountLocked 
    boolean passwordExpired 

    static constraints = { 
     username blank: false, unique: true 
     password blank: false 
    } 

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

    Set<Authority> getAuthorities() { 
     UserAuthority.findAllByUser(this).collect { it.authority } as Set 
    } 

    def beforeInsert() { 
     encodePassword() 
    } 

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

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

мой userauthority.groovy >>>

package common.auth 

import org.apache.commons.lang.builder.HashCodeBuilder 

class UserAuthority implements Serializable { 

    User user 
    Authority authority 

    boolean equals(other) { 
     if (!(other instanceof UserAuthority)) { 
      return false 
     } 

     other.user?.id == user?.id && 
      other.authority?.id == authority?.id 
    } 

    int hashCode() { 
     def builder = new HashCodeBuilder() 
     if (user) builder.append(user.id) 
     if (authority) builder.append(authority.id) 
     builder.toHashCode() 
    } 

    static UserAuthority get(long userId, long authorityId) { 
     find 'from UserAuthority where user.id=:userId and authority.id=:authorityId', 
      [userId: userId, authorityId: authorityId] 
    } 

    static UserAuthority create(User user, Authority authority, boolean flush = false) { 
     new UserAuthority(user: user, authority: authority).save(flush: flush, insert: true) 
    } 

    static boolean remove(User user, Authority authority, boolean flush = false) { 
     UserAuthority instance = UserAuthority.findByUserAndAuthority(user, authority) 
     if (!instance) { 
      return false 
     } 

     instance.delete(flush: flush) 
     true 
    } 

    static void removeAll(User user) { 
     executeUpdate 'DELETE FROM UserAuthority WHERE user=:user', [user: user] 
    } 

    static void removeAll(Authority authority) { 
     executeUpdate 'DELETE FROM UserAuthority WHERE authority=:authority', [authority: authority] 
    } 

    static mapping = { 
     id composite: ['authority', 'user'] 
     version false 
    } 
} 

И мое CreateUser действие, чтобы создать пользователя в AdministratorActionController >>>

package administrator 

import common.auth.User 

class AdmistratorActionController { 

    def springSecurityService 

    def index() { 
      redirect(controller: 'admistratorAction', action: 'createUser') 
    } 

    def createUser = { 
       User user = new User(params) 
       def password = user.password 
       def salt = user.username //depends on what you're using as a salt 
       user.password = springSecurityService.encodePassword(password, salt) 
       user.save() 
       flash.message = "User Create Successfully !!!" 
    } 
} 

ответ

5

Я думаю, что вы кодирующие пароль дважды, у вас уже есть закодировать() на beforeInsert в домене, я думаю, вам не нужно его снова закодировать.

+0

изменить линию user.password = springSecurityService.encodePassword (пароль, соль) в user.password = пароль , а затем проверить user.save (failOnError: правда) –

+0

Можете ли вы сказать мне, где я не должен кодировать его снова? –

+0

AdmistratorActionController -> createUser action, у вас есть user.password = springSecurityService.encodePassword (пароль, соль), который кодирует ваш пароль, даже если у вас есть encodePassword на beforeInsert в классе домена пользователя Я думаю, попробуйте с user.password = пароль , а затем сохранить объект пользователя –

1

Spring Security использование хэш пароля пользователя + соль. Соль используется для победы над заранее вычисленными атаками радужного стола, которые в противном случае можно было бы использовать для значительного повышения эффективности взлома базы данных хешированных паролей.См http://en.wikipedia.org/wiki/Salt_(cryptography)

Например, если мы используем username как хэш, реальное значение в базе данных будет:

md5(user.password + '|' + user.username) 

Так что для двух различных userw с таким же паролем:

  • пользователя: имя пользователя: 'user1', пароль: 123
  • пользователь: имя пользователя: 'user2', пароль: 123

вы получите два различных значения в базе данных:

  • md5('user1|123') == 975204d0650cc642730866d56f66b6fb
  • md5('user2|123') == aa12022115555842a7f80564940ae49d

Так что, если хакер имеет доступ к базе данных вас он не может угадать пароль.

Spring Security использует ту же функцию хэширования и соль для сохранения и загрузки пользователя. И если он не может найти пользователя, это, вероятно, означает, что вы использовали различную соль для первоначального сохранения и последующей загрузки из базы данных. Убедитесь, что у вас есть такие же источник соли, и она не меняется (как id поля, которые имеют null значения, когда вы просто создаете новый пользователь)

+0

У меня есть пользователь после установки spring-security. Я новичок в grails, и до сих пор могу думать, что Spring-Security не позволит сохранить пользователя с нулевым значением. На самом деле я не знаю. Я даю свой исходный код, чтобы вы могли мне помочь. Это будет так оценено. –

Смежные вопросы