2012-09-26 31 views
17

Aquí está mi configuración de seguridad de primavera:¿Cómo se redirige a la página de inicio si el usuario accede a la página de inicio de sesión después de iniciar sesión?

<http pattern="/auth/login" security="none" /> 
<http pattern="/auth/loginFailed" security="none" /> 
<http pattern="/resources/**" security="none" /> 

<http auto-config="true" access-decision-manager-ref="accessDecisionManager"> 
    <intercept-url pattern="/auth/logout" access="permitAll"/> 
    <intercept-url pattern="/admin/**" access="ADMINISTRATIVE_ACCESS"/> 
    <intercept-url pattern="/**" access="XYZ_ACCESS"/> 

    <form-login 
     login-page="/auth/login" 
     authentication-failure-url="/auth/loginFailed" 
     authentication-success-handler-ref="authenticationSuccessHandler" /> 
    <logout logout-url="/auth/logout" logout-success-url="/auth/login" /> 
</http> 

El authenticationSuccessHandler extiende la SavedRequestAwareAuthenticationSuccessHandler asegurar que el usuario es redirigido a la página que solicitó originalmente.

Sin embargo, desde /auth/login se marca como security="none", soy incapaz de volver a dirigir con éxito al usuario a la página de inicio si se accede a la página de inicio de sesión después de haber iniciado la sesión. Creo que esto es el derecho user experience también.

He intentado lo siguiente también, pero el objeto Principal es siempre null, presumiblemente debido al atributo security="none" de nuevo.

@RequestMapping(value = "/auth/login", method = GET) 
public String showLoginForm(HttpServletRequest request, Principal principal) { 
    if(principal != null) { 
     return "redirect:/"; 
    } 

    return "login"; 
} 
+0

Una forma en que puedo pensar es: 'if (session.getAttribute (" SPRING_SECURITY_CONTEXT ")! = Null) return" redirect:/";' (_que en realidad funciona! _) Pero estoy buscando un enfoque mucho más ordenado . – adarshr

+0

ver este http://stackoverflow.com/questions/13131122/spring-security-redirect-if-already-logged-in – Aalkhodiry

+0

Selecciona esta solución -> [aquí] [1] [1 ]: http://stackoverflow.com/a/28257013/3287459 – erginduran

Respuesta

9

He comprobado el tema más profundamente que la última vez y he descubierto que debe determinar si el usuario está autenticado por usted mismo en el controlador. Fila del cabrestante (dev Spring Security) says here:

primavera de Seguridad no tiene conocimiento de las interioridades de su aplicación (es decir, si usted desea hacer su entrada página de flexión sobre la base de si el usuario se registra o no) . Para mostrar su página de inicio cuando la página de inicio de sesión es solicitada y el usuario ha iniciado sesión use SecurityContextHolder en la página de inicio de sesión (o su controlador) y redirija o reenvíe al usuario a la página de inicio.

Así que la solución sería determinar si el usuario que solicita /auth/login es anónimo o no, algo como a continuación.

applicationContext-security.xml:

<http auto-config="true" use-expressions="true" 
     access-decision-manager-ref="accessDecisionManager"> 
    <intercept-url pattern="/auth/login" access="permitAll" /> 
    <intercept-url pattern="/auth/logout" access="permitAll" /> 
    <intercept-url pattern="/admin/**" access="ADMINISTRATIVE_ACCESS" /> 
    <intercept-url pattern="/**" access="XYZ_ACCESS" /> 

    <form-login login-page="/auth/login" 
     authentication-failure-url="/auth/loginFailed" 
     authentication-success-handler-ref="authenticationSuccessHandler" /> 
    <logout logout-url="/auth/logout" logout-success-url="/auth/login" /> 
</http> 

<beans:bean id="defaultTargetUrl" class="java.lang.String"> 
    <beans:constructor-arg value="/content" /> 
</beans:bean> 

<beans:bean id="authenticationTrustResolver" 
     class="org.springframework.security.authentication.AuthenticationTrustResolverImpl" /> 

<beans:bean id="authenticationSuccessHandler" 
     class="com.example.spring.security.MyAuthenticationSuccessHandler"> 
    <beans:property name="defaultTargetUrl" ref="defaultTargetUrl" /> 
</beans:bean> 

Añadir a applicationContext.xml definición de frijol:

<bean id="securityContextAccessor" 
    class="com.example.spring.security.SecurityContextAccessorImpl" /> 

que es de clase

public final class SecurityContextAccessorImpl 
     implements SecurityContextAccessor { 

    @Autowired 
    private AuthenticationTrustResolver authenticationTrustResolver; 

    @Override 
    public boolean isCurrentAuthenticationAnonymous() { 
    final Authentication authentication = 
     SecurityContextHolder.getContext().getAuthentication(); 
    return authenticationTrustResolver.isAnonymous(authentication); 
    } 
} 

implementación sencilla Interfaz

public interface SecurityContextAccessor { 
    boolean isCurrentAuthenticationAnonymous(); 
} 

(SecurityContextHolder accessing code is decoupled from controller, I followed suggestion from this answer, por lo tanto, SecurityContextAccessor interfaz.)

Y por último pero no menos importante redirigir la lógica en el controlador:

@Controller 
@RequestMapping("/auth") 
public class AuthController { 
    @Autowired 
    SecurityContextAccessor securityContextAccessor; 

    @Autowired 
    @Qualifier("defaultTargetUrl") 
    private String defaultTargetUrl; 

    @RequestMapping(value = "/login", method = RequestMethod.GET) 
    public String login() { 
    if (securityContextAccessor.isCurrentAuthenticationAnonymous()) { 
     return "login"; 
    } else { 
     return "redirect:" + defaultTargetUrl; 
    } 
    } 
} 

Definición defaultTargetUrl Cadena de frijol parece un truco, pero yo don' Tenemos una mejor manera de no codificar url ... (En realidad, en nuestro proyecto usamos <util:constant> con una clase que contiene campos de cadenas estáticas finales.) Pero funciona después de todo.

+0

si estoy usando spring useretailsService para autenticar usuarios, cómo ingresar el código si el usuario está autenticado y no es anónimo. –

+0

@MahmoudSaleh userDetailsService no tiene nada que ver con esta apprach, siempre que coloque el objeto de autenticación en SecurityContext debería funcionar. Si no funciona, haga una pregunta por separado y proporcione su configuración. – Xaerxess

4

Implementar una redirección interceptor para este propósito:

El interceptor (implementando HandlerInterceptor interfaz) comprobar si alguien intenta acceder a la página de inicio de sesión, y si esta persona ya ha iniciado sesión, a continuación, el interceptor envía una redirección a la Página de inicio.

public class LoginPageRedirectInterceptor extends HandlerInterceptorAdapter {  

    private String[] loginPagePrefixes = new String[] { "/login" }; 

    private String redirectUrl = "/index.html"; 

    private UrlPathHelper urlPathHelper = new UrlPathHelper(); 

    @Override 
    public boolean preHandle(HttpServletRequest request, 
          HttpServletResponse response, 
          Object handler) throws Exception { 

     if (isInLoginPaths(this.urlPathHelper.getLookupPathForRequest(request)) 
          && isAuthenticated()) { 
      response.setContentType("text/plain"); 
      sendRedirect(request, response); 
      return false; 
     } else { 
      return true; 
     } 
    } 

    private boolean isAuthenticated() { 
     Authentication authentication = 
         SecurityContextHolder.getContext().getAuthentication(); 
     if (authentication == null) { 
      return false; 
     } 
     if (authentication instanceof AnonymousAuthenticationToken) { 
      return false; 
     } 
     return authentication.isAuthenticated(); 
    } 

    private void sendRedirect(HttpServletRequest request, 
           HttpServletResponse response) { 

     String encodedRedirectURL = response.encodeRedirectURL(
           request.getContextPath() + this.redirectUrl); 
     response.setStatus(HttpStatus.SC_TEMPORARY_REDIRECT); 
     response.setHeader("Location", encodedRedirectURL); 
    } 

    private boolean isInLoginPaths(final String requestUrl) { 
     for (String login : this.loginPagePrefixes) { 
      if (requestUrl.startsWith(login)) { 
       return true; 
      } 
     } 
     return false; 
    } 
} 
+0

Dónde definir este interceptor –

+0

@Viswanath L: con la etiqueta del interceptor config xml: http://spring.io/blog/2009/12/21/mvc-simplifications-in-spring-3-0/ – Ralph

-1

Puede intentar comprobar

if(SecurityContextHolder.getContext().getAuthentication() == null) 

True significa que el usuario no está autenticado, y por lo tanto se pueden enviar a la página de inicio de sesión. No sé cuán robusto/confiable es esto, pero parece razonable intentarlo.

+1

A down votar sin un comentario es cobardía y traiciona su propia falta de conocimiento. – pyetti

5

También podría restringir su página de acceso a ROLE_ANONYMOUS y establecer un <access-denied-handler />:

<access-denied-handler ref="accessDeniedHandler" /> 
<intercept-url pattern="/auth/login" access="ROLE_ANONYMOUS" /> 

Y en su cheque manipulador si el usuario ya está autenticado:

@Service 
public class AccessDeniedHandler extends AccessDeniedHandlerImpl { 
    private final String HOME_PAGE = "/index.html"; 

    @Override 
    public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException, ServletException { 
     Authentication auth = SecurityContextHolder.getContext().getAuthentication(); 
     if (auth != null && !(auth instanceof AnonymousAuthenticationToken)) { 
      response.sendRedirect(HOME_PAGE); 
     } 

     super.handle(request, response, e); 
    } 
} 
0

Se puede mantener el flujo sencillo por access-denied-page atributo en el elemento http o como dtrunk dice escribir controlador para el acceso denegado, así como. la configuración sería como

<http access-denied-page="/403" ... > 
<intercept-url pattern="/login" access="ROLE_ANONYMOUS" /> 
<intercept-url pattern="/user/**" access="ROLE_USER" /> 
<intercept-url pattern="/admin/**" access="ROLE_ADMIN" /> 
<form-login login-page="/login" default-target-url="/home" ... /> 
... 
</http> 

en el controlador de /403

@RequestMapping(value = "/403", method = RequestMethod.GET) 
public String accessDenied() { //simple impl 
    return "redirect:/home"; 
} 

y para /home

@RequestMapping(value = "/home", method = RequestMethod.GET) 
public String home(Authentication authentication) { 
// map as many home urls with Role 
    Map<String, String> dashBoardUrls = new HashMap<String, String>(); 
    dashBoardUrls.put("ROLE_USER", "/user/dashboard"); 
    dashBoardUrls.put("ROLE_ADMIN", "/admin/dashboard"); 

    String url = null; 

    Collection<? extends GrantedAuthority> grants = authentication 
      .getAuthorities(); 
// for one role per user 
    for (GrantedAuthority grantedAuthority : grants) { 
     url = dashBoardUrls.get(grantedAuthority.getAuthority()); 
    } 
    if (url == null) 
     return "/errors/default_access_denied.jsp"; 

    return "redirect:" + url; 
} 

y cuando usted hace solicitud de /admin/dashboard sin iniciada la sesión, volverá a dirigir /login automáticamente por seguridad

0
<http pattern="/login" auto-config="true" disable-url-rewriting="true"> 
    <intercept-url pattern="/login" access="ROLE_ANONYMOUS"/> 
    <access-denied-handler error-page="/index.jsp"/> 
</http> 
Cuestiones relacionadas