如何使用Spring安全登录页面传递其他参数

Bha*_*has 40 spring spring-security

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

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

sou*_*ica 47

有很多方法可以做到这一点,但官方的方法是使用自定义AuthenticationDetailsAuthenticationDetailsSource子类分别为Spring WebAuthenticationDetailsWebAuthenticationDetailsSource.将额外字段添加到自定义,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()来访问您的额外字段.

  • 没有太多文档 - 您必须从`UsernamePasswordAuthenticationFilter`的工作原理推断它 - 它使用`WebAuthenticationDetailsS​​ource`并将`WebAuthenticationDetails`添加到`UsernamePasswordAuthenticationToken`. (5认同)

小智 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); 
    } 
}
Run Code Online (Sandbox Code Playgroud)

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

UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;
Run Code Online (Sandbox Code Playgroud)

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

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

<custom-filter ref="beanForYourCustomFilterFromStep1" position="FORM_LOGIN_FILTER"/>
Run Code Online (Sandbox Code Playgroud)

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

  • @Bhas,您如何修改UserDetailsS​​ervice来获取会话变量? (4认同)

Kam*_*kol 23

sourcedelica提到使用AuthenticationDetailsSource和自定义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>
Run Code Online (Sandbox Code Playgroud)

创建一个新类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);
    }
}
Run Code Online (Sandbox Code Playgroud)

和相关的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 */ }
}
Run Code Online (Sandbox Code Playgroud)


GMs*_*soF 7

如果您使用的是 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);
    }
}
Run Code Online (Sandbox Code Playgroud)


Nic*_* Lu 5

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

步骤1:遵循@ user1322340提供的所有步骤

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

<listener>
    <listener-class>
       org.springframework.web.context.request.RequestContextListener
    </listener-class>
</listener>
Run Code Online (Sandbox Code Playgroud)

步骤3:使用以下代码获取属性:

RequestContextHolder.getRequestAttributes().getAttribute("yourAttributeName", RequestAttributes.SCOPE_SESSION);
Run Code Online (Sandbox Code Playgroud)

步骤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)
                ...
    }
}
Run Code Online (Sandbox Code Playgroud)