Вопрос по spring, spring-security – Как передать дополнительный параметр с помощью весенней страницы входа в систему безопасности

38

Я пытаюсь установить имя базы данных в качестве входного параметра запроса со страницы входа в систему безопасности Spring. В настоящее время я получаю только имя пользователя, которое было получено с помощью Spring Security.SecurityContextHolder.getContext().getAuthentication().

Как получить доступ к дополнительному полю, которое было установлено на странице входа в систему?

Посмотри наUsernamePasswordAuthenticationFilter, Он используется по умолчанию на любой странице входа. vacuum
Вы хотите передать этот параметр перед входом в систему или получить параметры после входа в систему из БД? vacuum
Я хочу получить значение параметра запроса перед подключением к БД, я хотел решить, к какой БД пользователю необходимо подключиться, основываясь на значениях выбора, указанных на экране входа в систему. Bhas
да, я пытаюсь решить это таким образом. Но я пропустил какую-то часть там и столкнулся с ошибками. Пожалуйста, дайте мне знать, если у вас есть идея или рабочий образец (конфигурация) этого. Bhas
Я не думаю, что Spring имеет возможность сделать это из коробки. В любом случае, вы можете создать наш собственный фильтр аутентификации и получить этот параметр изHttpRequest объект. vacuum

Ваш Ответ

8   ответов
25

Вот простой способ (не проверенный, но я верю, что это будет работать)

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) В вашемUserDetailsService реализация, измените вашу реализацию:

UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException;

чтобы получить переменную сеанса, которую делает фильтр из шага 1).

3) в вашем<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

@Bhas, как вы изменили UserDetailsService, чтобы получить переменную сеанса?
Большое спасибо за вашу информацию. Я реализовал это, это работало хорошо. Bhas
Существует менее инвазивный способ сделать это и не нарушая договорUserDetailsService, Я согласен с @sourcedelica. Также эээ мойanswer аналогичный вопрос для более подробного примера.
0

Простой способ:

1) зарегистрировать RequestContextListener

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

2) И в основной класс:

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

3) После этого мы можем принимать параметры в пользовательских заголовках:

request.getHeader("OrganizationId")
1

которая использует конфигурацию Java, следующие простые шаги работают хорошо.

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");
3

рибутов сеанса в функции 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. Если вы получили ошибку & quot;authenticationManager must be specified& Quot ;. после регистрации вашего фильтра в конфиге. Вам нужно установить 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)
                ...
    }
}
22

sourcedelica упомянутое использованиеAuthenticationDetailsSource и обычайAuthenticationDetails..

добавлятьauthentication-details-source-ref атрибут с идентификатором компонента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>

Создать новый класс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 */ }
}
смотрите ответ @sourcedelica:SecurityContextHolder.getContext().getAuthentication().getDetails()
@raupach Должно быть что-то не так с вашей конфигурацией безопасности. Если хотите, можете взять мой пример сGithub для отладки.
Не работал для меня. AuthenticationDetailsSource вызывает buildDetails после входа в систему, и моего параметра GET больше нет. Использование Spring 3.1.6
тогда как я могу использоватьCustomWebAuthenticationDetails ?
@diegosahagun Во время звонкаJdbcDaoImpl.loadUsersByUsername все жеSecurityContext не заполнен текущимAuthenticationотсюдаnull ссылка. В вашем случае вам нужен кастомAuthenticationProvider который способен обрабатывать ваш дополнительный параметр. В этом случае вы не можетеUserDetailsService, Может быть, вы можете уточнить свою проблему в отдельном вопросе и получить несколько ответов.
0

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

Step 2.

Добавьте следующее в ваш метод класса, где вы хотите получить дополнительный параметр:

RequestAttributes attribs = RequestContextHolder.getRequestAttributes();

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

Теперь вы можете получить дополнительный параметр следующим образом, предполагая, что дополнительный параметр называется & quot; loginType & quot ;:

request.getParameter("loginType") 
2

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

но официальный способ сделать это - использоватьAuthenticationDetails а такжеAuthenticationDetailsSourceподклассы SpringWebAuthenticationDetails а такжеWebAuthenticationDetailsSourceсоответственно. Добавьте дополнительное поле в пользовательскийWebAuthenticationDetails и есть обычайWebAuthenticationDetailsSource получить данные из запроса на заполнение поля.

В Spring Security 3.1 его легко настроить с помощьюauthentication-details-source-ref атрибут<form-login> элемент.

В 3.0 вы должны использоватьBeanPostProcessor, Существует пример в FAQ по безопасности Spring наиспользование BeanPostProcessor для настройки пользовательского WebAuthenticationDetailsSource.

Когда это будет сделано, вы можете вызвать SecurityContextHolder.getContext (). GetAuthentication (). GetDetails (), чтобы получить доступ к вашему дополнительному полю.

Спасибо за пользовательскую идею AuthenticationDetails. Это интересно. Вы говорите, что это официально, но я не могу найти никакой официальной документации об этой технике. Есть ли?
Спасибо Ericacm, The реализовали решение, предоставленное Taylor Mingos, и оно отлично сработало для меня. Bhas
Там не так много документации - вы должны сделать вывод, какUsernamePasswordAuthenticationFilter работает - он используетWebAuthenticationDetailsSource и добавляетWebAuthenticationDetails кUsernamePasswordAuthenticationToken.
Расширение Spring Security - это разочаровывающий процесс ...

Похожие вопросы