[SPRING] 대체 인증없이 다른 로그인 양식을 인증하기위한 다른 UsernamePasswordAuthToken을 사용하는 여러 AuthenticationProvider
SPRING대체 인증없이 다른 로그인 양식을 인증하기위한 다른 UsernamePasswordAuthToken을 사용하는 여러 AuthenticationProvider
스프링 보안으로 작업하는 동안 스택 오버 플로우에서 흥미로운 스레드를 살펴 보았지만 LDAP 및 직원에 대한 직원과 다른 인증 공급자에 대해 두 명의 사용자 세트를 인증해야했습니다. 스레드는 수락 된 솔루션을 제공하여 직원과 고객을 구별하는 라디오 버튼이있는 단일 로그인 양식을 가지며 userType을 기반으로 로그인 요청을 구별하고 다른 authenticationToken (customerAuthToken / employeeAuthToken)을 설정하고 인증 요청이 진행되는 사용자 정의 인증 필터를 갖습니다. 두 가지 AuthenticationProvider 구현이 있으며 토큰을 지원하여 인증이 수행되고 결정됩니다. 이러한 방식으로 스레드는 스프링 보안이 기본적으로 제공하는 폴백 인증을 피하기 위해 흥미로운 솔루션을 제공 할 수있었습니다.
여러 진입 점을 갖도록 Spring Security 3.x 구성 스레드를 살펴보십시오.
대답은 완전히 XML 구성에 있기 때문입니다. 방금 솔루션을 Java 구성에서 사용할 수 있기를 원했습니다. 나는 그 답을 게시 할 것입니다.
이제 스프링 버전의 진화와 함께 내 질문은 내 대답 외에도 새로운 기능 / 최소 구성으로 동일한 기능을 가질 수 있습니까?
해결법
-
==============================
1.이 스레드는 완전한 정보를 제공 했으므로 Java 구성 참조 코드를 게시하고 있습니다.
이 스레드는 완전한 정보를 제공 했으므로 Java 구성 참조 코드를 게시하고 있습니다.
여기서 나는 다음과 같은 것을 가정하고있다. 1. 사용자와 관리자는 두 명의 사용자 집합입니다. 메모리 인증에서 두 가지 모두를 사용하는 것이 간편합니다. -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); }}
CustomAuthenticationProvider-관리자 용
@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); } }
CustomAuthenticationProvider-사용자 용
@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); } }
CustomFilter에 필요한 CustomHandlers
@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"); } }
대체 인증없이 다중 인증 구성을 이해하는 데 도움이되기를 바랍니다.
from https://stackoverflow.com/questions/57881749/multiple-authenticationprovider-with-different-usernamepasswordauthtoken-to-auth by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] Spring AOP-setter를 호출하기 전에 오래된 필드 값을 얻습니다. (0) | 2019.09.13 |
---|---|
[SPRING] 마이크로 서비스에 대한 직접 호출을 허용하지 마십시오. API Gateway를 통해서만 허용 (0) | 2019.09.13 |
[SPRING] 기본 URL을 유추 할 수 없습니다. 동적 서블릿 등록을 사용하거나 API가 API 게이트웨이 뒤에있는 경우에 일반적입니다. (0) | 2019.09.11 |
[SPRING] 스프링 프레임 워크를 경량 컨테이너로 만드는 것은 무엇입니까? (0) | 2019.09.11 |
[SPRING] save () 전에 스프링 데이터 JPA가 SELECT를 수행하지 못하게하려면 어떻게합니까? (0) | 2019.09.11 |