44

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

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

4

8 回答 8

47

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

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

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

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

于 2012-04-09T19:33:27.463 回答
27

详细阐述@Vacuum 的评论

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

  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); 
    } 
}
  1. 在您的UserDetailsService实施中,修改您的实施:
UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;

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

  1. 在您的<http />安全设置中,用您的自定义过滤器覆盖默认过滤器
<custom-filter ref="beanForYourCustomFilterFromStep1" position="FORM_LOGIN_FILTER"/>

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

于 2012-04-09T18:14:20.107 回答
23

sourcedelica提到 usingAuthenticationDetailsSource和 custom AuthenticationDetails。这是一个例子。

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>

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

和相关的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 */ }
}
于 2014-05-31T10:13:38.390 回答
9

如果您使用 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);
    }
}
于 2017-10-13T01:56:42.897 回答
5

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

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

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

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

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

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

第 4 步:在 Spring Security 配置中注册您的过滤器。如果您收到错误“必须指定 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)
                ...
    }
}
于 2016-06-30T12:11:53.253 回答
3

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

  • 在配置中的 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");
    
于 2016-07-22T14:46:29.953 回答
0

简单的方法:

1)注册RequestContextListener

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

2)和主课:

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

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

request.getHeader("OrganizationId")
于 2017-10-14T11:44:28.007 回答
0

最简单的方法只需两步:

第1步。

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

第2步。

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

RequestAttributes attribs = RequestContextHolder.getRequestAttributes();

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

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

request.getParameter("loginType") 
于 2018-01-11T10:24:48.937 回答