web-dev-qa-db-fra.com

Comment passer un paramètre supplémentaire avec la page de connexion Spring Security

J'essaie de définir le nom de la base de données comme paramètre d'entrée de la demande à partir de la page de connexion de sécurité Spring. À l'heure actuelle, je ne reçois que le nom d'utilisateur qui a été récupéré à l'aide de la sécurité de sécurité SecurityContextHolder.getContext().getAuthentication().

Comment accéder au champ supplémentaire défini sur la page de connexion?

38
Bhas

Explications sur le commentaire de @ Vacuum

Voici un moyen simple (non testé, mais je crois que cela fonctionnerait)

1) Créez une nouvelle classe ExUsernamePasswordAuthenticationFilter qui étendra le filtre par défaut, récupérera le paramètre supplémentaire et le stockera dans la session. Cela ressemblera à ceci:

    public class ExUsernamePasswordAuthenticationFilter extends UsernamePasswordAuthenticationFilter {

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        final String dbValue = request.getParameter("dbParam");
        request.getSession().setAttribute("dbValue", dbValue);

        return super.attemptAuthentication(request, response); 
    } 
}

2) Dans votre implémentation UserDetailsService, modifiez votre implémentation de:

UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;

récupérer la variable de session que le filtre de l'étape 1) met à disposition. 

3) dans votre configuration de sécurité <http />, remplacez le filtre par défaut par votre filtre personnalisé

<custom-filter ref="beanForYourCustomFilterFromStep1" position="FORM_LOGIN_FILTER"/>

Consultez cette partie de la documentation pour plus d'informations sur les filtres personnalisés: http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-custom- filtres

25
user1322340

Il existe plusieurs façons de procéder, mais la méthode officielle consiste à utiliser une variable AuthenticationDetails et AuthenticationDetailsSource personnalisée, en sous-classant les variables WebAuthenticationDetails et WebAuthenticationDetailsSource de Spring, respectivement. Ajoutez le champ supplémentaire à la variable WebAuthenticationDetails personnalisée et demandez à la variable WebAuthenticationDetailsSource d'obtenir les données de la demande pour renseigner le champ. 

Dans Spring Security 3.1, il est facile de configurer en utilisant l'attribut authentication-details-source-ref de l'élément <form-login>.

En 3.0, vous devez utiliser un BeanPostProcessor. Il existe un exemple dans Spring Security FAQ sur en utilisant un BeanPostProcessor pour configurer un WebAuthenticationDetailsSource personnalisé .

Une fois que cela est fait, vous pouvez appeler SecurityContextHolder.getContext (). GetAuthentication (). GetDetails () pour accéder à votre champ supplémentaire.

46
sourcedelica

sourcedelica mentionné en utilisant AuthenticationDetailsSource et une coutume AuthenticationDetails. Voici un exemple.

Ajoutez l'attribut authentication-details-source-ref avec l'ID de bean customWebAuthenticationDetailsSource à form-login:

<security:http>
    <security:intercept-url pattern="/**" access="..." />
    <security:form-login authentication-details-source-ref="customWebAuthenticationDetailsSource" login-page="..." />
    <security:logout logout-success-url="..." />
</security:http>

Créer une nouvelle classe CustomWebAuthenticationDetailsSource:

package security;

import org.springframework.security.authentication.AuthenticationDetailsSource;
import org.springframework.security.web.authentication.WebAuthenticationDetails;

import javax.servlet.http.HttpServletRequest;

public class CustomWebAuthenticationDetailsSource implements AuthenticationDetailsSource<HttpServletRequest, WebAuthenticationDetails> {
    @Override
    public WebAuthenticationDetails buildDetails(HttpServletRequest context) {
        return new CustomWebAuthenticationDetails(context);
    }
}

et la CustomWebAuthenticationDetails correspondante:

package security;

import org.springframework.security.web.authentication.WebAuthenticationDetails;
import javax.servlet.http.HttpServletRequest;

public class CustomWebAuthenticationDetails extends WebAuthenticationDetails {

    private final String yourParameter;

    public CustomWebAuthenticationDetails(HttpServletRequest request) {
        super(request);
        yourParameter = request.getParameter("yourParameter");
    }

    public String getyourParameter() {
        return yourParameter;
    }

    //TODO override hashCode, equals and toString to include yourParameter
    @Override
    public int hashCode() { /* collapsed */ }
    @Override
    public boolean equals(Object obj) { /* collapsed */ }
    @Override
    public String toString() { /* collapsed */ }
}
22
Kamill Sokol

@ user1322340 ne fournit pas les détails d'implémentation pour obtenir les attributs de session dans la fonction loadUserByUsername:

Étape 1: suivez toutes les étapes fournies par @ user1322340.

Étape 2: Vous devez ajouter une configuration dans web.xml comme ceci:

<listener>
    <listener-class>
       org.springframework.web.context.request.RequestContextListener
    </listener-class>
</listener>

Étape 3: Utilisez ce code pour obtenir les attributs:

RequestContextHolder.getRequestAttributes().getAttribute("yourAttributeName", RequestAttributes.SCOPE_SESSION);

Étape 4: Enregistrez votre filtre dans la configuration de sécurité du printemps. Si vous obtenez une erreur " authenticationManager doit être spécifié ". après avoir enregistré votre filtre dans config. Vous devez définir un authenticationManagerBean pour votre filtre étendu et le configurer de la manière suivante:

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    public ExUsernamePasswordAuthenticationFilter exUsernamePasswordAuthenticationFilter()
            throws Exception {
        ExUsernamePasswordAuthenticationFilter exUsernamePasswordAuthenticationFilter = new ExUsernamePasswordAuthenticationFilter();
        exUsernamePasswordAuthenticationFilter
                .setAuthenticationManager(authenticationManagerBean());
        return exUsernamePasswordAuthenticationFilter;
    }

    @Bean
    @Override
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        RequestMatcher requestMatcher = new RequestMatcher() {
            @Override
            public boolean matches(HttpServletRequest httpServletRequest) {
                if (httpServletRequest.getRequestURI().indexOf("/api", 0) >= 0) {
                    return true;
                }
                return false;
            }
        };

        http
                .addFilterBefore(exUsernamePasswordAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                ...
    }
}
3
Nicholas Lu

Il existe un moyen plus simple si vous utilisez la variable personnalisée AuthenticationProvider. Vous pouvez simplement injecter HttpServletRequest et récupérer votre paramètre supplémentaire:

@Component
public class CustomAuthenticationProvider implements AuthenticationProvider {

    @Autowired(required = false)
    private HttpServletRequest request;

    @Autowired
    private MyAccountService myAccountService;

    @Override
    public Authentication authenticate(Authentication authentication) {

        System.out.println("request testing= " + request.getParameter("testing"));

        .....
    }

    @Override
    public boolean supports(Class<?> authentication) {
        return authentication.equals(UsernamePasswordAuthenticationToken.class);
    }
}
2
GMsoF

Pour Spring Security 3.0 ou version ultérieure, qui utilise la configuration Java, procédez comme suit. 

  • Ajoutez votre filtre avant l'objet UserNameandPasswordAuthenticationFilter dans l'objet HttpSecurity de configure.

    http.addFilterBefore(new YourFilter(), UsernamePasswordAuthenticationFilter.class);
    
  • Laissez le filtre avoir une ligne comme celle-ci pour obtenir les champs nécessaires dans votre demande de Session.

    if(requestPath != null &&requestPath.equals("/login") ) {
            session.setAttribute("yourParam",req.getParameter("yourParam"));
        }
    
  • Plus tard, vous pourrez obtenir la valeur du paramètre de la session dans n'importe quelle classe en tant que:

    String yourParam =(String)request.getSession().getAttribute("yourParam");
    
1
user6625940

Manière simple: 

1) enregistrer RequestContextListener

@Bean
public RequestContextListener requestContextListener(){
    return new RequestContextListener();
}

2) Et à la classe principale:

HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.
currentRequestAttributes()).
getRequest();

3) Après cela, nous pouvons prendre des paramètres dans des en-têtes personnalisés:

request.getHeader("OrganizationId")

La manière la plus simple en seulement 2 étapes:

Étape 1.

Ajoutez l'écouteur suivant dans web.xml:

<listener>
    <listener-class>
        org.springframework.web.context.request.RequestContextListener
    </listener-class>
</listener>

<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value></param-value>
</context-param>

Étape 2.

Ajoutez ce qui suit dans votre méthode de classe où vous voulez obtenir des paramètres supplémentaires:

RequestAttributes attribs = RequestContextHolder.getRequestAttributes();

if (RequestContextHolder.getRequestAttributes() != null) {
    HttpServletRequest request = ((ServletRequestAttributes) attribs).getRequest();
}

Vous pouvez maintenant obtenir votre paramètre supplémentaire de la manière suivante, en supposant que le paramètre supplémentaire s'appelle "loginType":

request.getParameter("loginType") 
0
Sanjeev Kumar Gupta