example - spring security grails 3.3 1
Grails Spring Security: Al iniciar sesiĆ³n con una URL de destino se salta el flujo de trabajo posterior a la autenticaciĆ³n (2)
1) Sí, porque es un inicio de sesión "a petición".
2) Sí, puede configurarlo para usar siempre el valor predeterminado. El complemento de seguridad de primavera tiene una configuración para " successHandler.alwaysUseDefault ", cambia eso a true, por defecto es falso.
Además, si necesita más detalles, consulte los documentos de primavera para buscar la sección Establecer un destino de entrada posterior predeterminado .
3) Si aún desea crear el bean de sesión del usuario y luego redirigirlo a la URL original, tiene dos opciones: crear el bean en un filtro anterior o exponer los datos necesarios a través de un UserDetailsService personalizado. Personalmente iría por la ruta de un servicio personalizado de detalles.
En mi aplicación de Grails, he personalizado el flujo de trabajo de autorización de publicación escribiendo un controlador de autenticación auth personalizado (en resources.groovy) como se muestra a continuación.
authenticationSuccessHandler (MyAuthSuccessHandler) {
def conf = SpringSecurityUtils.securityConfig
requestCache = ref(''requestCache'')
defaultTargetUrl = conf.successHandler.defaultTargetUrl
alwaysUseDefaultTargetUrl = conf.successHandler.alwaysUseDefault
targetUrlParameter = conf.successHandler.targetUrlParameter
useReferer = conf.successHandler.useReferer
redirectStrategy = ref(''redirectStrategy'')
superAdminUrl = "/admin/processSuperAdminLogin"
adminUrl = "/admin/processAdminLogin"
userUrl = "/admin/processUserLogin"
}
Como puede hacerlo en las últimas tres líneas del cierre anterior, dependiendo de la Función otorgada al Usuario que inicia sesión, la estoy redirigiendo para separar las acciones dentro del AdminController donde se crea y almacena un UserSessionBean personalizado en la sesión.
Funciona bien para un caso de inicio de sesión normal que en mi aplicación es así:
- El usuario accede a la aplicación a través de
http://localhost:8080/my-app/
Ohttp://localhost:8080/my-app/login/auth
- Ella ingresa su identificación de acceso y contraseña válidos y procede.
- La aplicación accede internamente a MyAuthSuccessHandler, que redirige a AdminController teniendo en cuenta la función otorgada a este usuario.
- El UserSessionBean se crea y almacena en la sesión
- El usuario es llevado a la página de inicio de la aplicación
También he escrito un MyUserDetailsService
personalizado extendiendo GormUserDetailsService
que se accede correctamente en el flujo anterior.
ESCENARIO DE PROBLEMAS
Considere la posibilidad de que un usuario acceda directamente a un recurso protegido (en este caso, el controlador está asegurado con la anotación @Secured
) dentro de la aplicación.
- El usuario hace clic en
http://localhost:8080/my-app/inbox/index
- La aplicación la redirecciona a
http://localhost:8080/my-app/login/auth
- El usuario ingresa su identificación de inicio de sesión y contraseña válidas
- El usuario se dirige a
http://localhost:8080/my-app/inbox/index
El MyAuthSuccessHandler
se omite por completo en este proceso y, por lo tanto, mi UserSessionBean no se crea, lo que genera errores al seguir utilizándolo en los lugares donde se accede a UserSessionBean .
PREGUNTAS:
- En el escenario del problema, ¿omite la aplicación
MyAuthSuccessHandler
porque hay una URL objetivo a la que redirigir al iniciar sesión? - ¿Podemos forzar que el proceso pase siempre por
MyAuthSuccessHandler
incluso con la URL objetivo presente? - Si la respuesta a 2 es no, ¿existe alguna alternativa en cuanto a cómo y dónde se puede crear UserSessionBean ?
Puede implementar EventListener personalizado para manejar el proceso posterior a la conexión, sin interrumpir la URL solicitada por el usuario original.
En config.groovy, inserte un elemento de configuración:
grails.plugins.springsecurity.useSecurityEventListener = true
En you resources.groovy, agrega un bean como este:
import com.yourapp.auth.LoginEventListener
beans = {
loginEventListener(LoginEventListener)
}
Y crea un eventListener en src / groovy así:
package com.yourapp.auth
import org.springframework.context.ApplicationListener;
import org.springframework.security.authentication.event.InteractiveAuthenticationSuccessEvent
import org.springframework.web.context.request.RequestContextHolder as RCH
class LoginEventListener implements
ApplicationListener<InteractiveAuthenticationSuccessEvent> {
//deal with successful login
void onApplicationEvent(InteractiveAuthenticationSuccessEvent event) {
User.withTransaction {
def user = User.findByUsername(event.authentication.principal.username)
def adminRole = Role.findByAuthority(''ROLE_ADMIN'')
def userRole = Role.findByAuthority(''ROLE_USER'')
def session = RCH.currentRequestAttributes().session //get httpSession
session.user = user
if(user.authorities.contains(adminRole)){
processAdminLogin()
}
else if(user.authorities.contains(userRole)){
processUserLogin()
}
}
}
private void processAdminLogin(){ //move admin/processAdminLogin here
.....
}
private void processUserLogin(){ //move admin/processUserLogin here
.....
}
}
Hecho.