Spring 에서 xml을 이용하여 기존의 POST로 진행하는 Login 기능에다가
GET으로 Login진행할 수 있는 기능을 추가하여 사용할 수 있는 방법이다.
(따라서, 일반적인 Form 로그인 방식이 먼저 필요하다.)
2019/11/02 - [Develop/Spring] - Spring security 로그인(DB에 있는 아이디 조회)
1. Filter 생성
기존의 Form Login방식은 POST로 데이터를 받기 때문에, Filter를 생성한다.
Username과 Password를 받을 것이기 때문에 UsernamePasswordAuthenticationFilter를 상속받는다.
public class GetLoginFilter extends UsernamePasswordAuthenticationFilter {
@Override
public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response)
throws AuthenticationException {
// TODO Auto-generated method stub
return super.attemptAuthentication(request, response);
}
}
2. Provider 생성
사실 기존에 POST로 로그인하는 기능이 존재하기 때문에 굳이 작성을 하지 않아도 되나, 혹시 GET방식에서 패스워드가 없어도 아이디만 있으면 로그인을 성공시키거나 이러한 기능을 하고 싶다면 생성을 해야한다.
public class GetLoginProvider implements AuthenticationProvider {
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// TODO Auto-generated method stub
return null;
}
@Override
public boolean supports(Class<?> authentication) {
// TODO Auto-generated method stub
return false;
}
}
3. security xml에 Filter, Provider 등록
3.1 Filter 등록
filter 연결을 위해 class에 위에 생성한 GetLoginFilter를 연결해준다.
filterProcessesUrl을 등록해 Get방식으로 Login할 때 어떤 URL을 사용할지 등록한다.
name="authenticationManager" 에 기존의 POST방식의 인증을 사용하고 싶다면 ref="org.springframework.security.authenticationManager" 로 사용하면 되나,
여기서는 Provider를 만들었기 때문에 위에서 생성한 Provider를 getLogin이라는 이름으로 등록해 사용할 것이다.
인증성공핸들러와 인증실패핸들러는 기존에 이미 사용하고 있던 것이 있기 때문에 기존의 것을 사용해줘도 무관하거나 새로 만들어주어도 상관없다. (현재 글 작성 기준으로 이미 기존의 Form Login 방식이 있는 상태에서 Get Login을 설명하고 있기 때문)
postOnly는 Get으로 받을 것이기 때문에 false로 변경한다.
<beans:bean id="GetLoginFilter" class="net.a.test.login.GetLoginFilter">
<beans:property name="filterProcessesUrl" value="/getLogin" />
<!-- <beans:property name="authenticationManager" ref="org.springframework.security.authenticationManager" /> -->
<beans:property name="authenticationManager" ref="getLogin" />
<beans:property name="usernameParameter" value="id" />
<beans:property name="passwordParameter" value="password" />
<beans:property name="authenticationSuccessHandler" ref="loginSuccessHandler" />
<beans:property name="authenticationFailureHandler" ref="loginFailureHandler" />
<beans:property name="postOnly" value="false"/>
</beans:bean>
3.2 Provider 등록
위의 Filter에서 Provider를 등록하기 위해 Provider 또한 등록한다.
먼저, 아까 위의 2번에서 생성한 Provider를 bean으로 등록한다.
다음, 다시 등록한 bean을 authentication-manaer로 등록한다.
<beans:bean id="GetLoginProvider" class="net.a.test.login.GetLoginProvider" />
<authentication-manager id ="getLogin">
<authentication-provider ref="GetLoginProvider" />
</authentication-manager>
이렇게 Filter와 Provider를 등록하면 Get 방식으로 인증이 가능해진다.
4. Provider 수정
3.1의 Filter 등록의 authenticationManager에서 기존의 인증방식이아닌 새로 생성한 Provider 인증방식을
등록하였기 때문에 2번에서 생성한 Provider를 수정해주어야 한다.
기존의 Form Login 기능에 사용하던 userDetailsService와 , PasswordEncoder를 가져온다.
authenticate 함수에서 Get 파라미터로 가져온 name과 password를 입력한다.
다음, 기존에 사용하던 loadUserByUsername을 통해 DB에 저장되어있는 암호화된 password와 권한들을 가져온다.
그리고 passwordEncoder의 matchs 기능으로 Get파라미터로 가져온 평문의 password와 암호화된 password를
비교해 Passoword가 맞다면 인증을 성공시키고, 다르다면 Exception을 던진다.
public class GetLoginProvider implements AuthenticationProvider {
@Autowired
UserDetailsService userDetailsService;
@Autowired
PasswordEncoder passwordEncoder;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// TODO Auto-generated method stub
String name = authentication.getName();
String password = authentication.getCredentials().toString();
UserDetails userDetails = userDetailsService.loadUserByUsername(name);
Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
if(passwordEncoder.matches(password, userDetails.getPassword()))
return new UsernamePasswordAuthenticationToken(userDetails, authentication.getCredentials().toString(),
authorities);
else
throw new BadCredentialsException("authentication failed");
}
@Override
public boolean supports(Class<?> authentication) {
// TODO Auto-generated method stub
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
만약, 패스워드입력필요없이 아이디만으로 로그인하고 싶다면 아래와 같이 패스워드 비교 코드를 삭제하고 작성하면 된다.
public class GetLoginProvider implements AuthenticationProvider {
@Autowired
userDetailsService userDetailsService;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
// TODO Auto-generated method stub
String name = authentication.getName();
UserDetails userDetails = userDetailsService.loadUserByUsername(name);
Collection<? extends GrantedAuthority> authorities = userDetails.getAuthorities();
// use the credentials
// and authenticate against the third-party system
return new UsernamePasswordAuthenticationToken(userDetails, authentication.getCredentials().toString(),
authorities);
}
@Override
public boolean supports(Class<?> authentication) {
// TODO Auto-generated method stub
return authentication.equals(UsernamePasswordAuthenticationToken.class);
}
}
이러한 방식으로 기존의 POST로 진행하던 Form Login에서 Get Login 방식을 추가할 수 있다.
'Develop > Spring' 카테고리의 다른 글
Spring Tomcat JNDI 설정 (0) | 2020.11.17 |
---|---|
Spring Security Custom Filter (0) | 2020.11.09 |
Spring security 로그인(DB에 있는 아이디 조회) (0) | 2019.11.02 |
Spring Mybatis + MariaDB(HikariCP) 설정 (0) | 2019.10.24 |
Spring 3 에서 4로 migration (0) | 2019.10.22 |