JSF con Spring security – Redirigir a la página especificada después de inicio de sesión

Tengo una aplicación web que utiliza JSF y Spring security se utiliza para el inicio de sesión y la autorización.

Cuando un usuario escribe en una página específica y no está conectado, por ejemplo,localhost:8080/APP/page.xhtml, la aplicación redirige a la página de inicio de sesión que está bien. Después de eso, el usuario se registra, pero la página a la que se redirige a es index.xhtml que es el valor predeterminado de la página de bienvenida, y no page.xhtml.

Quiero el siguiente comportamiento: usuario va a localhost:8080/APP/page.xhtml, él se redirige a la sesión y después de que él debe ser redirigido a su página deseada – page.xhtml.

Editado – Fragmento de spring-security.xml:

 <security:http auto-config="true">
    <security:intercept-url pattern="/javax.faces.resource/*" access="IS_AUTHENTICATED_ANONYMOUSLY"/>
    <security:intercept-url pattern="/login.xhtml" access="IS_AUTHENTICATED_ANONYMOUSLY"/>

    <security:intercept-url pattern="/**" access="ROLE_UNALLOCATED, ROLE_MANAGER"/>
    <security:intercept-url pattern="/pages/management/" access="ROLE_MANAGER"/>
    <security:intercept-url pattern="/pages/requests/" access="ROLE_UNALLOCATED, ROLE_EMPLOYEE, ROLE_TEAM_LEADER, ROLE_MANAGER"/>

    <security:form-login login-page="/login.xhtml" 
                          />
    <security:logout logout-url="/j_spring_security_logout"
            logout-success-url="/login.xhtml"
            invalidate-session="true"/>
</security:http>

Alguna idea? Gracias

Edición:

Pensé que era porque:

 <!-- Welcome page -->
<welcome-file-list>
    <welcome-file>/index.xhtml</welcome-file>
</welcome-file-list>

de web.xml. He quitado esto, pero con el mismo resultado.

Posterior edición:

Me di cuenta de una línea en mi costumbre loginController después de if (authenticationResponseToken.isAuthenticated()) que es casi seguro que el origen del problema:

La loginController:

@ManagedBean(name = "loginController")
@SessionScoped
@Controller
public class LoginController implements Serializable {
private static final long serialVersionUID = 1L;

@Autowired
IUserService userService;

@Autowired
@Qualifier("authenticationManager")
protected AuthenticationManager authenticationManager;

//save the current user after login to be able to inject it in other places
//as needed
private User currentUser;

/**
 * This action logs the user in and returns to the secure area.
 * 
 * @return String path to secure area
 */
public String loginUsingSpringAuthenticationManager() {
    //get backing bean for simple redirect form
    LoginFormBackingBean loginFormBean = (LoginFormBackingBean) FacesUtils
            .getBackingBean("loginFormBean");

    //simple token holder
    Authentication authenticationRequestToken = createAuthenticationToken(loginFormBean);

    //authentication action
    try {
        Authentication authenticationResponseToken = authenticationManager
                .authenticate(authenticationRequestToken);

        Authentication authCopy = null;
        final Object principal = authenticationResponseToken.getPrincipal();
        if (principal instanceof LdapUserDetailsImpl) {
            LdapUserDetailsImpl userImpl = (LdapUserDetailsImpl) principal;
            userImpl.getUsername();

            //here check if we already have a User with his DN in the DB
            //get the User by DN
            User u = userService.getUserByDn(userImpl.getDn());

            //if a user with this DN does not exist in the DB, create a new
            //one with the DN from LDAP and the default settings for a new
            //user
            if (null == u) {
                u = userService.createNewUserFromDn(userImpl.getDn(),
                        userImpl.getUsername());
            }
            //set the obtained user as the current user
            setCurrentUser(u);
            List<GrantedAuthority> grAuth = new ArrayList<GrantedAuthority>();
            //after this, do the role authority stuff
            //here loop through user roles if he has more and
            if (null != u.getUserTeamRoles()) {
                for (UserTeamRole urt : u.getUserTeamRoles()) {
                    //here get role for every UserTeamRole
                    grAuth.add(new SimpleGrantedAuthority(urt.getRole()
                            .getName()));
                }
            }

            //add the above found roles to the granted authorities of the
            //current authentication
            authCopy = new UsernamePasswordAuthenticationToken(
                    authenticationResponseToken.getPrincipal(),
                    authenticationResponseToken.getCredentials(), grAuth);
        }

        SecurityContextHolder.getContext().setAuthentication(authCopy);
        //ok, test if authenticated, if yes reroute
        if (authenticationResponseToken.isAuthenticated()) {
            //lookup authentication success url, or find redirect parameter
            //from login bean
            return "index.xhtml?faces-redirect=true";
        }
    } catch (BadCredentialsException badCredentialsException) {
        //FacesMessage facesMessage = new FacesMessage(
        //"Login Failed: please check your username/password and try again.");
        //FacesContext.getCurrentInstance().addMessage(null, facesMessage);
        FacesContext.getCurrentInstance().addMessage(
                null,
                new FacesMessage(FacesMessage.SEVERITY_ERROR,
                        "Sample error message",
                        "Login Failed! Please check your credentials"));
    } catch (LockedException lockedException) {
        FacesMessage facesMessage = new FacesMessage(
                "Account Locked: please contact your administrator.");
        FacesContext.getCurrentInstance().addMessage(null, facesMessage);
    } catch (DisabledException disabledException) {
        FacesMessage facesMessage = new FacesMessage(
                "Account Disabled: please contact your administrator.");
        FacesContext.getCurrentInstance().addMessage(null, facesMessage);
    }

    return null;
}

private Authentication createAuthenticationToken(
        LoginFormBackingBean loginFormBean) {
    UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(
            loginFormBean.getUserName(), loginFormBean.getPassword());
    return usernamePasswordAuthenticationToken;
}

¿Cómo puedo redirigir a la página necesito? Tengo un loginBean que contiene el usuario y la contraseña y yo podría agregar un redirectUrl pero, ¿cómo puedo encontrar la url anterior de la ruta?

  • Podría publicar su completa http de configuración con intercept-url-s.
  • He añadido toda seguridad-http config
  • Intenta depurar org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler y ver si está siendo ejecutado y si se le redirige a la url correcta.
InformationsquelleAutor AndaP | 2013-01-22

4 Kommentare

  1. 5

    Primavera Seguridad implementa esta lógica para usted en el AbstractAuthenticationProcessingfilter (normalmente, mediante la aplicación concreta de UsernamePasswordAuthenticationFilter) mediante el uso de la SavedRequestAwareAuthenticationSuccesshandler (que utiliza el HttpSessionRequestCache bajo las sábanas). Puesto que usted ha escrito un controlador para autenticar (en lugar de utilizar el construido en el soporte), es necesario aplicar esta lógica a ti mismo. En lugar de implementar toda la lógica de usted mismo, usted puede volver a utilizar las mismas clases de Primavera Seguridad.

    Por ejemplo, su LoginController podría ser actualizado como sigue:

    public class LoginController implements Serializable {
        //... same as before ...
        private RequestCache requestCache = new HttpSessionRequestCache();
    
        public String loginUsingSpringAuthenticationManager() {
            //... just as you had been doing ...
    
            if (authenticationResponseToken.isAuthenticated()) {
                HttpServletRequest request = (HttpServletRequest)         
                  FacesContext.getCurrentInstance().getExternalContext().getRequest();
                HttpServletResponse response = (HttpServletResponse)         
                  FacesContext.getCurrentInstance().getExternalContext().getResponse();
    
                SavedRequest savedRequest = requestCache.getRequest(request, response);
    
                return savedRequest.getRedirectUrl();
            }
    
            //... same as you had ...
       }
    }
    • Hice esto, el problema es que mis páginas, utilice los componentes de PrimeFaces. Y probablemente debido a que, el savedRequest.getRedirectUrl devuelve este siempre: http://localhost:8080/APP/javax.faces.resource/jquery/jquery.js.xhtml?ln=primefaces. Yo inspeccionar el código fuente de la página y en el componente de la cabeza esta misma declaración se encuentra: <script type="text/javascript" src="/APP/javax.faces.resource/jquery/jquery.js.xhtml?ln=primefaces">
    • ¿Hay alguna razón por la que usted necesita para ser privado? A menos que tenga una razón para asegurar que el código javascript (que es, probablemente, sólo una copia de la biblioteca de jquery), parece como si probablemente debería hacer esta dirección pública. Tal vez usted quiere configurar todos los recursos públicos (es decir, <seguridad:intercept-url pattern=»/javax.las caras.recursos/**» access=»IS_AUTHENTICATED_ANONYMOUSLY»/>)?
    • Ok, he cambiado el patrón de <security:http pattern="/javax.faces.resource/*" security="none"/> y sigue siendo el mismo.
    • No estoy seguro si es sólo PARA el formato, pero el patrón /javax.faces.resource/* no coincide con /javax.faces.resource/jquery/jquery.js.xhtml?ln=primefaces. Asegúrese de que tiene el patrón para tener dos * al final. Por ejemplo: <security:http pattern="/javax.faces.resource/**" security="none"/>
    • Que es perfectamente correcto, funciona con /javax.faces.resource/**. Muchas gracias por la ayuda!
  2. 1

    Por defecto si default-target-url no está definido Spring Security intenta redireccionar a la url anterior, por lo que sólo necesita para eliminar default-target-url atributo de form-login etiqueta.

    <security:form-login login-page="/login.xhtml" />

    Actualización

    Si el filtro de la cadena de la ExceptionTranslationFilter en él, a continuación, se debe almacenar en caché de la solicitud HTTP. Así que en su personalizados loginController usted podría tratar de obtener una url de redirección de este caché solicitud.

    RequestCache requestCache = new HttpSessionRequestCache();
    SavedRequest savedRequest = requestCache.getRequest(request, response);
    String targetUrl = savedRequest.getRedirectUrl();

    Para inyectar solicitud al controlador de probar:

    private @Autowired HttpServletRequest request;

    o

    HttpServletRequest curRequest = ((ServletRequestAttributes) 
               RequestContextHolder.currentRequestAttributes()) .getRequest();
    • Hizo que, mismo resultado. después de la sesión en la que se va a indexar.xhtml
    • Que versión de primavera-seguridad están utilizando? También se están utilizando por defecto el filtro de la pila?
    • Estoy usando spring security 3.1.1. No estoy seguro de cuál es el valor predeterminado de filtro de la pila, estoy utilizando algunos <seguridad:intercept-url> patrones para proteger las páginas y las rutas de acceso.
    • Problema es que no tengo la «solicitud» y «respuesta» params en mi loginController
    • Para inyectar en su controlador.
    • No estoy seguro de cómo inyectar en ellos, hice esto: SavedRequest savedRequest = requestCache.getRequest( (HttpServletRequest) FacesContext.getCurrentInstance() .getExternalContext().getRequest(), (HttpServletResponse) FacesContext.getCurrentInstance() .getExternalContext().getResponse()); y la url que me sale es: http://localhost:8080/APP/javax.faces.resource/jquery/jquery.js.xhtml?ln=primefaces
    • Trate de private @Autowired HttpServletRequest request; o HttpServletRequest curRequest = ((ServletRequestAttributes) RequestContextHolder.currentRequestAttributes()) .getRequest();

  3. 0

    Cambio

    <security:form-login login-page="/login.xhtml" 
                             default-target-url="/index.xhtml" />

    a

    <security:form-login login-page="/login.xhtml" 
                             default-target-url="/page.xhtml" />
    • Esto haría que la aplicación vaya a la página.xhtml todo el tiempo en vez de índice.xhtml.
    • Yo sé. Lo siento @AndaP, entendí mal tu pregunta, acabo de dar cuenta ahora que usted escribió eg en frente de la dirección de ejemplo
  4. 0

    Tener el comportamiento que se describe, se debe agregar un resorte filtro de seguridad en su web.xml como siguiente :

    <filter>
        <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
    </filter>
    <filter-mapping>
        <filter-name>springSecurityFilterChain</filter-name>
        <url-pattern>/*</url-pattern>
        <dispatcher>FORWARD</dispatcher>
        <dispatcher>REQUEST</dispatcher>
        <dispatcher>ERROR</dispatcher>
        <dispatcher>INCLUDE</dispatcher>
    </filter-mapping>

    Y puede ser que tenga también para editar su spring-secruity.xml.
    vea este enlace para más información : Spring Security con DelegatingFilterProxy

    Comprobar esta discusión, es que parece que es similar a su pregunta, puede ser que te ayuda a : http://forum.springsource.org/showthread.php?128480-Redirecting-to-original-(unauthenticated-page)-after-spring-security-openid-authentic

    Espero que esto responde a tu pregunta 😉

    Aymen

    • La verdad es que tengo esa configuración en mi web.xml (sin ERROR y sin INCLUIR los casos), pero sigue siendo el mismo comportamiento. No estoy seguro de lo que debo modificar en el enlace que me dio, parece que tengo la misma config.
    • ¿Usar un filtro de autenticación en la primavera de configuración de seguridad? Puedo editar mi post y añadir otro enlace que puede ser de ayuda para usted.
    • podría usted por favor edita el post y pon tu loginController declarration y la implementación del método que contiene si (authenticationResponseToken.isAuthenticated()).

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea