2012-09-26 20 views
17

Ecco la mia primavera di configurazione di sicurezza:Come reindirizzare alla homepage se l'utente accede alla pagina di accesso dopo aver effettuato l'accesso?

<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> 

Il authenticationSuccessHandler estende la SavedRequestAwareAuthenticationSuccessHandler garantire che l'utente viene reindirizzato alla pagina che originariamente richiesto.

Tuttavia, dal momento che /auth/login è contrassegnato come security="none", non sono in grado di reindirizzare l'utente con successo alla homepage se si accede alla pagina di login dopo essere loggato. Credo che questo sia il diritto user experience troppo.

Ho provato anche il sotto ma l'oggetto Principal è sempre null, presumibilmente a causa dell'attributo security="none".

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

    return "login"; 
} 
+0

Un modo che posso pensare è: 'if (session.getAttribute (" SPRING_SECURITY_CONTEXT ")! = Null) restituisce" redirect:/";' (_che funziona davvero! . – adarshr

+0

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

+0

Si prega di verificare questa soluzione -> [qui] [1] [1 ]: http://stackoverflow.com/a/28257013/3287459 – erginduran

risposta

9

Ho controllato l'argomento più profondamente dell'ultima volta e ho scoperto che è necessario determinare se l'utente è autenticato da solo nel controller. Row Winch (dev Primavera di sicurezza) says here:

Primavera di sicurezza non è a conoscenza dei meccanismi interni della vostra applicazione (cioè se si desidera rendere il vostro login page flessione sulla base se l'utente è loggato o meno) . Per mostrare la tua pagina iniziale quando la pagina di login è richiesta e l'utente ha effettuato l'accesso usa SecurityContextHolder nella pagina di login (o il suo controller) e reindirizza o inoltra l'utente a la pagina iniziale.

Quindi soluzione sarebbe determinare se l'utente che richiede /auth/login è anonimo o meno, qualcosa di simile di seguito.

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> 

Aggiungi al applicationContext.xml definizione di fagioli:

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

che è la classe

public final class SecurityContextAccessorImpl 
     implements SecurityContextAccessor { 

    @Autowired 
    private AuthenticationTrustResolver authenticationTrustResolver; 

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

attuazione semplice Interfaccia

public interface SecurityContextAccessor { 
    boolean isCurrentAuthenticationAnonymous(); 
} 

(SecurityContextHolder accessing code is decoupled from controller, I followed suggestion from this answer, quindi SecurityContextAccessor interfaccia.)

E, ultimo ma non meno importante reindirizzare logica nel controllore:

@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; 
    } 
    } 
} 

Definizione defaultTargetUrl Fagiolino sembra un hack, ma io don' Ho un modo migliore di non usare l'url hardcode ... (In realtà nel nostro progetto usiamo <util:constant> con una classe contenente i campi di stringa finale statica.) Ma funziona dopotutto.

+0

se sto utilizzando spring useretailsService per autenticare gli utenti, come controllare il codice se l'utente è autenticato e non è anonimo? –

+0

@MahmoudSaleh userDetailsService non ha nulla a che fare con questo apprach, finché si mette l'oggetto di autenticazione in SecurityContext che dovrebbe funzionare. Se non funziona, fai una domanda separata e fornisci la tua configurazione. – Xaerxess

4

Implementare un reindirizzamento Interceptor per questo scopo:

Interceptor (attuazione HandlerInterceptor interfaccia) controllare se qualcuno tenta di accedere alla pagina di login, e se questa persona è già connesso, quindi l'intercettatore invia un redirect al pagina indice.

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

Dove definire questo intercettore –

+0

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

-1

Si può provare a controllare

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

vero significa che l'utente non è autenticato, e quindi possono essere inviati alla pagina di login. Non so quanto sia robusto/affidabile, ma sembra ragionevole provarci.

+1

A down votare senza commenti è codardia e tradisce la propria mancanza di conoscenza. – pyetti

5

Si potrebbe anche restringere la pagina di login per ROLE_ANONYMOUS e impostare un <access-denied-handler />:

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

E nel tuo assegno gestore se l'utente è già autenticato:

@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

È possibile mantenerlo semplice flusso per l'attributo access-denied-page nell'elemento http o come dtrunk detto di scrivere gestore per l'accesso negato come pure. la configurazione sarebbe come

<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> 

nel controller per /403

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

e per /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; 
} 

e quando si fa la richiesta per /admin/dashboard senza login, sarà reindirizzare /login automaticamente sicurezza

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> 
Problemi correlati