spring 如何使用spring security登录页面传递附加参数

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10074308/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 05:03:37  来源:igfitidea点击:

How to pass an additional parameter with spring security login page

springspring-security

提问by Bhas

I am trying to set the database name as the request input parameter from the spring security login page. At present I am only getting username that's been retrieved using spring security SecurityContextHolder.getContext().getAuthentication().

我正在尝试将数据库名称设置为 spring 安全登录页面的请求输入参数。目前我只得到使用 spring security 检索到的用户名SecurityContextHolder.getContext().getAuthentication()

How to access the additional field that's been set on the login page?

如何访问登录页面上设置的附加字段?

采纳答案by Bhas

Elaborating on @Vacuum's comment

详细说明@Vacuum 的评论

Here's a simple way (untested, but I believe this would work)

这是一个简单的方法(未经测试,但我相信这会奏效)

1) Create a new class ExUsernamePasswordAuthenticationFilterthat will extend the default filter and grab the additional parameter and store it in the session. It will look something like this:

1) 创建一个新类ExUsernamePasswordAuthenticationFilter,该类将扩展默认过滤器并获取附加参数并将其存储在会话中。它看起来像这样:

    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) In your UserDetailsServiceimplementation, modify your implementation of:

2) 在您的UserDetailsService实现中,修改您的实现:

UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;

to grab the session variable that the filter from step 1) makes available.

获取步骤 1) 中过滤器可用的会话变量。

3) in your <http />security set-up, override the default filter with your custom one

3)在您的<http />安全设置中,用您的自定义过滤器覆盖默认过滤器

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

Refer to this part of the documentation for more info about custom filters: http://static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-custom-filters

有关自定义过滤器的更多信息,请参阅文档的这一部分:http: //static.springsource.org/spring-security/site/docs/3.1.x/reference/springsecurity-single.html#ns-custom-filters

回答by sourcedelica

There's a number of ways to do this but the official way to do it is using a custom AuthenticationDetailsand AuthenticationDetailsSource, subclassing Spring's WebAuthenticationDetailsand WebAuthenticationDetailsSource, respectively. Add the extra field to the custom WebAuthenticationDetailsand have the custom WebAuthenticationDetailsSourceget the data from the request to populate the field.

有许多方法可以做到这一点,但它使用的是自做正式的方式AuthenticationDetailsAuthenticationDetailsSource,继承Spring的WebAuthenticationDetailsWebAuthenticationDetailsSource分别。将额外的字段添加到自定义,WebAuthenticationDetails并让自定义WebAuthenticationDetailsSource从请求中获取数据以填充该字段。

In Spring Security 3.1 it's easy to configure by using the authentication-details-source-refattribute of the <form-login>element.

在 Spring Security 3.1 中,很容易通过使用元素的authentication-details-source-ref属性进行配置<form-login>

In 3.0 you have to use a BeanPostProcessor. There is an example in the Spring Security FAQ on using a BeanPostProcessor to configure a custom WebAuthenticationDetailsSource.

在 3.0 中,您必须使用BeanPostProcessor. Spring Security FAQ 中有一个关于使用 BeanPostProcessor 配置自定义 WebAuthenticationDetailsS​​ource 的示例

Once this is done then you can call SecurityContextHolder.getContext().getAuthentication().getDetails() to get access to your extra field.

完成此操作后,您可以调用 SecurityContextHolder.getContext().getAuthentication().getDetails() 以访问您的额外字段。

回答by Kamill Sokol

sourcedelicamentioned using AuthenticationDetailsSourceand a custom AuthenticationDetails. Here is an example.

sourcedelica提到使用AuthenticationDetailsSource和自定义AuthenticationDetails. 这是一个例子。

Add authentication-details-source-refattribute with the bean id customWebAuthenticationDetailsSourceto form-login:

authentication-details-source-ref将带有 bean id 的属性添加customWebAuthenticationDetailsSourceform-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>

Create a new class CustomWebAuthenticationDetailsSource:

创建一个新类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);
    }
}

and the related CustomWebAuthenticationDetails:

和相关的CustomWebAuthenticationDetails

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 */ }
}

回答by Nicholas Lu

@user1322340 does not provide implement detail to get session Attributes in loadUserByUsername function:

@user1322340 没有提供在 loadUserByUsername 函数中获取会话属性的实现细节:

Step 1: Follow all the step provided by @user1322340

第 1 步:按照@user1322340 提供的所有步骤进行操作

Step 2: you need add one configuration in web.xml like this:

第 2 步:您需要在 web.xml 中添加一个配置,如下所示:

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

Step 3: Use such code to get attributes:

第 3 步:使用此类代码获取属性:

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

Step 4: Register your filter in spring security config. If you get a error "authenticationManager must be specified". after you register your filter in config. You need set a authenticationManagerBean for your extended filter and config it in that way:

第 4 步:在 spring 安全配置中注册您的过滤器。如果您收到错误“必须指定 authenticationManager”。在配置中注册过滤器后。您需要为扩展过滤器设置一个 authenticationManagerBean 并以这种方式配置它:

@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)
                ...
    }
}

回答by GMsoF

There is an easier way if you are using custom AuthenticationProvider. You can just inject HttpServletRequestand retrieve your extra parameter:

如果您使用的是 custom ,则有一种更简单的方法AuthenticationProvider。您可以注入HttpServletRequest并检索您的额外参数:

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

回答by user6625940

For spring security 3.0 or above which uses java configuration, the following simple steps works well.

对于使用java配置的spring security 3.0及以上版本,下面的简单步骤效果很好。

  • Add a your of filter before the UserNameandPasswordAuthenticationFilter in HttpSecurity object in configure.

    http.addFilterBefore(new YourFilter(), UsernamePasswordAuthenticationFilter.class);
    
  • Let the filter has a line like this to get the needed fields in your request to session.

    if(requestPath != null &&requestPath.equals("/login") ) {
            session.setAttribute("yourParam",req.getParameter("yourParam"));
        }
    
  • Later you may get the parameter value from the session in any class as:

    String yourParam =(String)request.getSession().getAttribute("yourParam");
    
  • 在配置中的 HttpSecurity 对象中的 UserNameandPasswordAuthenticationFilter 之前添加您的过滤器。

    http.addFilterBefore(new YourFilter(), UsernamePasswordAuthenticationFilter.class);
    
  • 让过滤器有这样一行来获取会话请求中所需的字段。

    if(requestPath != null &&requestPath.equals("/login") ) {
            session.setAttribute("yourParam",req.getParameter("yourParam"));
        }
    
  • 稍后您可以从任何类中的会话中获取参数值:

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

回答by Игорь Демянюк

Simple way:

简单的方法:

1) register RequestContextListener

1)注册RequestContextListener

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

2) And to main class:

2)到主类:

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

3) After that we can take params in custom headers:

3) 之后,我们可以在自定义标头中获取参数:

request.getHeader("OrganizationId")

回答by Sanjeev Kumar Gupta

Simplest way in only 2 steps:

最简单的方法,只需两步:

Step 1.

第1步。

Add the following listener in web.xml:

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

Step 2.

第2步。

Add the following in your class method where you want to get additional param:

在您想要获取额外参数的类方法中添加以下内容:

RequestAttributes attribs = RequestContextHolder.getRequestAttributes();

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

Now you can get your additional parameter by the following, assuming the extra parameter is named "loginType":

现在您可以通过以下方式获取额外参数,假设额外参数名为“loginType”:

request.getParameter("loginType")