2012-07-05 13 views
6

Jestem nowicjuszem w Spring Security 3. Używam ról, aby użytkownicy mogli się zalogować.Jak dodać niestandardowy filtr po autoryzacji użytkownika w aplikacji wiosna

Chcę dodać wartość sesji po autoryzacji użytkownika do aplikacji. Może potrzebuję jakiegoś filtra, aby przekierował mnie do mojej metody, która dodaje pewną wartość sesji. Skonfigurowałem plik security.xml, ale nie jestem pewien, czy robię właściwe rzeczy. Pomocne mogą być wszelkie przykłady w tym kierunku. Którą klasę filtra należy użyć? Jak skonfigurować plik security.xml?

<custom-filter ref="authenticationFilter" after="FORM_LOGIN_FILTER "/> 

<beans:bean id="authenticationFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter"> 
    <beans:property name="filterProcessesUrl" value="/j_spring_security_check" /> 
    <beans:property name="authenticationManager" ref="authenticationManager" /> 
    <beans:property name="authenticationSuccessHandler" ref="successHandler" /> 
</beans:bean> 

<beans:bean id="successHandler" class="org.dfci.sparks.datarequest.security.CustomAuthorizationFilter"/> 

Moja metoda klasy filtra Potrzebuję dodać wartość sesji.

public class CustomAuthorizationFilter implements AuthenticationSuccessHandler { 

    @Override 
    public void onAuthenticationSuccess(HttpServletRequest request, 
      HttpServletResponse response, Authentication authentication) 
      throws IOException, ServletException { 
     Set<String> roles = AuthorityUtils.authorityListToSet(authentication 
       .getAuthorities()); 
     if (roles.contains("ROLE_USER")) { 
      request.getSession().setAttribute("myVale", "myvalue"); 
     } 
    } 
} 

Edycja kodu

I zostały zmodyfikowane mój plik security.xml i klasa plik

<custom-filter ref="authenticationFilter" after="FORM_LOGIN_FILTER "/> 
public class CustomAuthorizationFilter extends GenericFilterBean { 

    /* 
    * ServletRequestAttributes attr = (ServletRequestAttributes) 
    * RequestContextHolder.currentRequestAttributes(); HttpSession 
    * session=attr.getRequest().getSession(true); 
    */ 
    @Autowired 
    private UserService userService; 

    @Override 
    public void doFilter(ServletRequest request, ServletResponse response, 
      FilterChain chain) throws IOException, ServletException { 

     try { 
      chain.doFilter(request, response); 

        HttpServletRequest req = (HttpServletRequest) request; 
        HttpSession session = req.getSession(true); 
        Authentication authentication = SecurityContextHolder 
          .getContext().getAuthentication(); 
        Set<String> roles = AuthorityUtils 
          .authorityListToSet(authentication.getAuthorities()); 
        User user = null;     
         if (true) { 
          session.setAttribute("Flag", "Y"); 
         } 
      } 

     } catch (IOException ex) { 
      throw ex; 
     } 
    } 

} 

Które wywołuje za każdym URL. Czy jest to jakakolwiek alternatywa dla metody filtrowania połączeń tylko raz, gdy użytkownik jest uwierzytelniany?

+0

Na czym polega problem z powyższym kodem? Czy nie otrzymujesz atrybutu myValue sesji w adresie URL sukcesu logowania? –

+0

@SunilChavan: Wywołuje ten filtr, zanim użytkownik zostanie uwierzytelniony. – Raje

+0

Jak możesz tak mówić? Zobacz szczegóły (API) [http://static.springsource.org/spring-security/site/docs/3.0.x/apidocs/org/springframework/security/web/authentication/AuthenticationSuccessHandler.html]. Wyraźnie mówi, że po udanym uwierzytelnieniu wywołuje metodę onAuthenticationSuccess. –

Odpowiedz

8

Wreszcie udało mi się mój problem rozwiązany. Zamiast używania filtra dodałem program obsługi, który wywołuje się tylko dla pomyślnego zalogowania.

dodaje się następujący wiersz w security.xml

<form-login login-page="/" authentication-failure-url="/?login_error=1" default-target-url="/" always-use-default-target="false" 
     authentication-success-handler-ref="authenticationSuccessHandler"/> 
     <logout /> 

<beans:bean id="authenticationSuccessHandler" class="security.CustomSuccessHandler"/> 

także Dodałem jeden niestandardowy obsługi, która dodać atrybut sesji.

package security; 

import java.io.IOException; 
import java.security.GeneralSecurityException; 

import javax.servlet.ServletException; 
import javax.servlet.http.HttpServletRequest; 
import javax.servlet.http.HttpServletResponse; 
import javax.servlet.http.HttpSession; 
import org.springframework.beans.factory.annotation.Value; 
import org.springframework.security.core.Authentication; 
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler; 

public class CustomSuccessHandler extends 
      SavedRequestAwareAuthenticationSuccessHandler { 
    @Override 
    public void onAuthenticationSuccess(final HttpServletRequest request, 
      final HttpServletResponse response, final Authentication authentication) 
      throws IOException, ServletException { 
     super.onAuthenticationSuccess(request, response, authentication); 

     HttpSession session = request.getSession(true); 

     try { 
      if (CurrentUser.isUserInRole("USER")) { 
       session.setAttribute("Flag", "user"); 
      } 
     } catch (Exception e) { 
      logger.error("Error in getting User()", e); 
     } 
    } 

} 
+0

Wywołuję wspólną funkcję od usłyszenia, ale zwraca wyjątek wskaźnika pustego, który uruchamia jdbctemplate. – Zigri2612

+0

Exce. Threadpoolexecutor nieznane źródło – Zigri2612

0

Można użyć standardowego filtru java (mam na myśli implementację interfejsu filtru). Po prostu umieść go po filtrze uwierzytelniania w web.xml (oznacza to, że przejdzie później w łańcuchu filtrów i zostanie wywołany po łańcuchu filtrów bezpieczeństwa).

public class CustomFilter implements Filter{ 

    @Override 
    public void destroy() { 
     // Do nothing 
    } 

    @Override 
    public void doFilter(ServletRequest req, ServletResponse res, 
      FilterChain chain) throws IOException, ServletException { 

      HttpServletRequest request = (HttpServletRequest) req; 

      Authentication authentication = SecurityContextHolder.getContext().getAuthentication(); 

      Set<String> roles = AuthorityUtils.authorityListToSet(authentication.getAuthorities()); 
      if (roles.contains("ROLE_USER")) { 
       request.getSession().setAttribute("myVale", "myvalue"); 
      } 

      chain.doFilter(req, res); 

    } 

    @Override 
    public void init(FilterConfig arg0) throws ServletException { 
     // Do nothing 
    } 

} 

Fragment web.xml:

<!-- The Spring Security Filter Chain --> 
<filter> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> 
</filter> 

<!-- Pay attention to the url-pattern --> 
<filter-mapping> 
    <filter-name>springSecurityFilterChain</filter-name> 
    <url-pattern>/*</url-pattern> 
    <!-- <dispatcher>FORWARD</dispatcher> 
<dispatcher>REQUEST</dispatcher> --> 
</filter-mapping> 

<!-- Your filter definition --> 
<filter> 
    <filter-name>customFilter</filter-name> 
    <filter-class>com.yourcompany.test.CustomFilter</filter-class> 
</filter> 
<filter-mapping> 
    <filter-name>customFilter</filter-name> 
    <url-pattern>/VacationsManager.jsp</url-pattern> 
</filter-mapping> 
+0

Edytuję przykład do twojego przypadku. – dimas

+0

Dzięki za dawanie przykładu. Postępuję zgodnie z tymi samymi krokami, o których wspomniałeś. Zmodyfikowałem swój kod, ale to wywołanie metody filtru dla każdego adresu URL. Czy jest to alternatywa, aby zadzwonić tylko raz, gdy użytkownik jest uwierzytelniony? – Raje

+0

Jeśli rozumiem, że jesteś poprawny, powinieneś ustawić poprawny wzorzec adresu URL dla filtra (na przykład twoja strona logowania/login.jsp). W takim przypadku filtr przechwyci tylko żądanie dla twojej strony logowania. W przypadku innych adresów URL filtr nie zostanie wykonany. – dimas

Powiązane problemy