Несколько AuthenticationProvider с разными UsernamePasswordAuthToken для аутентификации различных форм входа без резервной аутентификации
Во время работы с Spring Security я взглянул на интересный поток в stackru, там требовалось аутентифицировать два набора пользователей против другого поставщика аутентификации, говорят сотрудники противLDAP
и клиент против DATABASE
. В потоке появилось принятое решение: иметь единую форму входа с переключателем, чтобы отличать сотрудника от клиента, и иметь настраиваемый фильтр аутентификации, который различает запрос входа в систему на основе userType и устанавливает разные authenticationToken(customerAuthToken/employeeAuthToken), и запрос обрабатывается для аутентификации. Будет дваAuthenticationProvider
реализация и аутентификация выполняются и определяются поддерживающим токеном. Таким образом, поток смог предоставить интересное решение, позволяющее избежать резервной аутентификации, которую Spring Security обеспечивает по умолчанию.
Взгляните на поток Настройка Spring Security 3.x, чтобы иметь несколько точек входа
Поскольку ответ полностью находится в конфигурации xml. Я просто хотел, чтобы решение было доступно в конфигурации java. Я отправлю это в ответ.
Теперь мой вопрос, с развитием весенней версии, возможно ли иметь такую же функциональность с помощью каких-либо новых функций / минимальных конфигураций, кроме моего ответа?
1 ответ
Поскольку этот поток дал полную информацию, я просто публикую коды для справки по конфигурации Java.
Здесь я предполагаю следующее:
1. Пользователь и администратор как две группы пользователей.
2. Для простоты использования аутентификации в памяти для обоих.
- Если userType - User, должны работать только учетные данные пользователя.
- Если userType - Admin, должны работать только учетные данные администратора.
- И должен иметь возможность предоставлять один и тот же интерфейс приложения с разными полномочиями.
И коды
Вы можете скачать рабочий код из моего репозитория на github
CustomAuthenticationFilter
@Component
public class MyAuthenticationFilter extends UsernamePasswordAuthenticationFilter
{
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException
{
UsernamePasswordAuthenticationToken authToken = null;
if ("user".equals(request.getParameter("userType")))
{
authToken = new UserUsernamePasswordAuthenticationToken(request.getParameter("userName"), request.getParameter("password"));
}
else
{
authToken = new AdminUsernamePasswordAuthenticationToken(request.getParameter("userName"), request.getParameter("password"));
}
setDetails(request, authToken);
return super.getAuthenticationManager().authenticate(authToken);
}
}
CustomAuthentictionTokens
public class AdminUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken
{
public AdminUsernamePasswordAuthenticationToken(Object principal, Object credentials)
{
super(principal, credentials);
}
public AdminUsernamePasswordAuthenticationToken(Object principal, Object credentials,
Collection<? extends GrantedAuthority> authorities)
{
super(principal, credentials, authorities);
}
}
public class UserUsernamePasswordAuthenticationToken extends UsernamePasswordAuthenticationToken
{
public UserUsernamePasswordAuthenticationToken(Object principal, Object credentials)
{
super(principal, credentials);
}
public UserUsernamePasswordAuthenticationToken(Object principal, Object credentials,
Collection<? extends GrantedAuthority> authorities)
{
super(principal, credentials, authorities);
}}
CustomAuthentictionProvider - For Admin
@Component
public class AdminCustomAuthenticationProvider implements AuthenticationProvider
{
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
{
String username = authentication.getName();
String password = authentication.getCredentials().toString();
if (username.equals("admin") && password.equals("admin@123#"))
{
List<GrantedAuthority> authorityList = new ArrayList<>();
GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_ADMIN");
authorityList.add(authority);
return new UserUsernamePasswordAuthenticationToken(username, password, authorityList);
}
return null;
}
@Override
public boolean supports(Class<?> authentication)
{
return authentication.equals(AdminUsernamePasswordAuthenticationToken.class);
}
}
CustomAuthentictionProvider - For User
@Component
public class UserCustomAuthenticationProvider implements AuthenticationProvider
{
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException
{
String username = authentication.getName();
String password = authentication.getCredentials().toString();
if (username.equals("user") && password.equals("user@123#"))
{
List<GrantedAuthority> authorityList = new ArrayList<>();
GrantedAuthority authority = new SimpleGrantedAuthority("ROLE_USER");
authorityList.add(authority);
return new UserUsernamePasswordAuthenticationToken(username, password, authorityList);
}
return null;
}
@Override
public boolean supports(Class<?> authentication)
{
return authentication.equals(UserUsernamePasswordAuthenticationToken.class);
}
}
CustomHandlers required for CustomFilter
@Component
public class CustomAuthenticationFailureHandler implements AuthenticationFailureHandler
{
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException
{
response.sendRedirect(request.getContextPath() + "/login?error=true");
}
}
@Component
public class CustomAuthenticationSuccessHandler implements AuthenticationSuccessHandler
{
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException
{
HttpSession session = request.getSession();
if (session != null)
{
session.removeAttribute(WebAttributes.AUTHENTICATION_EXCEPTION);
}
response.sendRedirect(request.getContextPath() + "/app/user/dashboard");
}
}
И наконец SpringSecurityConfiguration
@Configuration
@EnableWebSecurity
public class SpringSecurityConfig extends WebSecurityConfigurerAdapter
{
@Autowired
DataSource dataSource;
@Autowired
private AdminCustomAuthenticationProvider adminCustomAuthenticationProvider;
@Autowired
private UserCustomAuthenticationProvider userCustomAuthenticationProvider;
@Autowired
private CustomAuthenticationSuccessHandler customAuthenticationSuccessHandler;
@Autowired
private CustomAuthenticationFailureHandler customAuthenticationFailureHandler;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.authenticationProvider(adminCustomAuthenticationProvider);
auth.authenticationProvider(userCustomAuthenticationProvider);
}
@Bean
public MyAuthenticationFilter myAuthenticationFilter() throws Exception
{
MyAuthenticationFilter authenticationFilter = new MyAuthenticationFilter();
authenticationFilter.setAuthenticationSuccessHandler(customAuthenticationSuccessHandler);
authenticationFilter.setAuthenticationFailureHandler(customAuthenticationFailureHandler);
authenticationFilter.setRequiresAuthenticationRequestMatcher(new AntPathRequestMatcher("/login", "POST"));
authenticationFilter.setAuthenticationManager(authenticationManagerBean());
return authenticationFilter;
}
@Override
protected void configure(final HttpSecurity http) throws Exception
{
http
.addFilterBefore(myAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
.csrf().disable()
.authorizeRequests()
.antMatchers("/resources/**", "/", "/login")
.permitAll()
.antMatchers("/config/*", "/app/admin/*")
.hasRole("ADMIN")
.antMatchers("/app/user/*")
.hasAnyRole("ADMIN", "USER")
.antMatchers("/api/**")
.hasRole("APIUSER")
.and().exceptionHandling()
.accessDeniedPage("/403")
.and().logout()
.logoutSuccessHandler(new CustomLogoutSuccessHandler())
.invalidateHttpSession(true);
http.sessionManagement().maximumSessions(1).expiredUrl("/login?expired=true");
}
}
Надеюсь, это поможет понять настройку множественной аутентификации без резервной аутентификации.