Customizando o Spring Security
16/11/2012 14:07
1
Olá pessoal,

Estou passando por um problema para customizar o spring security com classes do meu sistema.

Eu já tenho uma solução, mas estou a procura de uma mais elegante. Eu não sei se a solução que estou procurando é possível de ser aplicada, apesar de, logicamente, ter sentido o que estou procurando.

Eu tenho três classes:
- Usermodule
- Profile
- Ruleprofile

As suas implementações são simples. Vide abaixo:


class Usermodule implements Serializable {

transient springSecurityService;
transient UsermoduleService;

String name;

String login;

String username
String password;

String email;

String description;

Boolean valid = Boolean.TRUE;

static hasMany = [profiles: Profile, modulos: Module]

public String toString() {
return this.name
}

static constraints = {
name(blank:Boolean.FALSE, nullable: Boolean.FALSE)
login(blank:Boolean.FALSE, nullable: Boolean.FALSE, unique: Boolean.TRUE)
password(blank:Boolean.FALSE, nullable: Boolean.FALSE, password: Boolean.TRUE)
email(blank:Boolean.FALSE, nullable: Boolean.FALSE, unique: Boolean.TRUE)
description(blank:Boolean.TRUE, nullable: Boolean.TRUE)
valid(blank:Boolean.FALSE, nullable: Boolean.FALSE)
}


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

def beforeInsert() {
encodePassword()
}

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

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

Set<Ruleprofile> getAuthorities() {
UsermoduleService.getUserProfileRules(this.id) as Set
}
}



class Ruleprofile implements Serializable {

String authority

String name
String description

static belongsTo = Profile

static hasMany = [profiles: Profile]

static constraints = {
name(nullable:false, blank:false, unique:true)
description(nullable:true, blank:true)
authority(nullable:false, blank:false, unique:true)
}

static mapping = {
cache true
}

@Override
public String toString() {
return authority;
}
}



class Profile implements Serializable{
String name
String description

Module module

static belongsTo = [Module, Usermodule]

static hasMany = [rules: Ruleprofile, users: Usermodule]

public String toString() {
return this.name
}

static constraints = { name(blank:false, nullable:false, unique:true)
description(blank:true, nullable:true)
module(blank:true, nullable:true)
}
}



Tenho uma classe de serviço usada para resolver a lógica de busca por regras:

class UsermoduleService {

public def getUserProfileRules(Long id) {
def usermoduleInstance = Usermodule.get(id)
Set<Ruleprofile> rules = new HashSet<Ruleprofile>();

if (usermoduleInstance) {
usermoduleInstance.profiles.each{ profile->
rules.addAll(profile.rules);
}
}

return rules;
}
}



Como eu mudei a forma como o comando "s2-quickstart" trabalha, eu mudei o mapeamento na classe Config.groovy para:



grails.plugins.springsecurity.userLookup.userDomainClassName = 'br.com.ntc.moduloseguranca.Usermodule'
grails.plugins.springsecurity.authority.className = 'br.com.ntc.moduloseguranca.Ruleprofile'



Quando eu defino uma regra:


@Secured(['ROLE_ADMIN'])
def create() {
[usermoduleInstance: new Usermodule(params)]
}


Mesmo que um usuário tenha uma perfil com a regra definida acima, o sistema não deixa acessar o método. Nem mesmo entra no método da classe de serviço definida acima ("getUserProfileRules").

Há alguma mapeamento que esteja faltando para que o sistema entenda de onde buscar as regras?

Desde já abrigadeço.
Tags: spring security customizar mapeamento


0
Oi EGT,

está me cheirando a um problema na sua classe UserModuleService, você já a testou para ver se está realmente retornando um Set de authorities?


0
Sim, Henrique.

Inclusive a minha solução:


transient UsermoduleService;

def create() {
if (!UsermoduleService.getUserProfileRules(session.user.id).contains('ROLE_ADMIN')) {
redirect(action: "list");
}

[usermoduleInstance: new Usermodule(params)]
}


Resolve o problema normalmente. Eu estou achando que seja algo do Spring que eu deva ter que configurar para ele encontrar o método.

Lembrando que o método "getUserProfileRules" não é chamado quado a tag "@Secured(['ROLE_ADMIN']) " está definida acima do método.

Att,
16/11/2012 14:40


0
Opa EGT, você incluiu a linha abaixo na configuração do plugin?


grails.plugins.springsecurity.securityConfigType = "Annotation"


No caso, o Spring Security sempre vai executar o método getAuthorities da sua classe de domínio pra obter as permissões, sendo assim a implementação do seu serviço não impactaria diretamente no funcionamento do plugin.


0
Oi Henrique,

Também fiz isso. Outras configurações que apliquei foram:


grails.plugins.springsecurity.userLookup.authoritiesPropertyName = 'rules'
grails.plugins.springsecurity.authority.nameField = 'authority'


Até então continua sem acessar aos métodos. Não sei exatamente como o spring fazer o invoke do método para resolver o mapeamento. Eu verifiquei em alguns foruns e o pessoal acaba reescrevendo o invoke do próprio spring para debugar. O que para mim é bem improdutivo... mas se funciona, não posso negar o seu uso.
16/11/2012 17:24


0
Oi EGT,

bem esquisito isto. Vou postar no Twitter pra ver se alguém aqui consegue ajudar ok?


2
Cara,

Percebea q no metodo getAuthorities da domain usuario vc esta
referenciando a classe de servico usando inicial maiuscula, como se
O metodo la fosse abstrato, mas n é.

Por padrao o construtorninjetado cria uma instancia com o mesmo nome da classe porem
Iniciando com minuscula. No domain usuario metodo getaauthorities TROQUE UserModuloService por
userModuloService...

Desculpem os erros digitacao...to no cell
17/11/2012 16:40


1
Olá EGT,

O texto enviado pelo Maurício está correto e além do que ele citou você precisará remover o "transient". Faça as injeções de dependência usando "def":


def springSecurityService;
def usermoduleService;


Porém não acho que fazer só isso irá resolver o problema. O SpringSecurity usa SpEL para validar o que você colocou na anotação
@Secured
por padrão e com isso para que a verificação do "ROLE_ADMIN" funcione, tente usar
@Secured("hasRole('ROLE_ADMIN')" )
e por último garanta que o serviço esteja com o import correto:

import grails.plugins.springsecurity.Secured;


Caso não dê certo, nos envie o seu projeto para que a gente possa olhar analisar, talvez seja um detalhe bem simples.
18/11/2012 18:35



Ainda não faz parte da comunidade???

Para se registrar, clique aqui.


Aprenda Groovy e Grails com a Formação itexto!

Newsletter Semana Groovy

Assinar

Envie seu link!


Livro de Grails


/dev/All

Os melhores blogs de TI (e em português) em um único lugar!

 
Creative Commons
RSS Grails Brasil é mantido por itexto Consultoria.
Em caso de problemas contacte Henrique Lobo Weissmann (Kico) por e-mail: kico@itexto.com.br
Todo o conteúdo presente neste site adota o Creative Commons como licença padrão.
Ver: 4.14.0
itexto