반응형
로그인 실패 시 후처리에 대한 포스팅 정리입니다.
로그인 실패시
1. 로그인 정보 담기
2. 세션 없이 에러 전달하기
3. 3회 이상 틀리면 계정 잠그기
폴더 구성
security-context.xml
<beans:bean id="customizeAuthenticationFailureHandler"
class="com.otrodevym.mfaw.common.security.custom.CustomizeAuthenticationFailureHandler">
<beans:property name="loginIdName" value="user_id"></beans:property>
<beans:property name="loginPwdName" value="password"></beans:property>
<beans:property name="errorMsgName" value="ERRORMSG"></beans:property>
<beans:property name="defaultFailureUrl"
value="/login?error=true"></beans:property>
</beans:bean>
CustomizeAuthenticationFailureHandler.java
public class CustomizeAuthenticationFailureHandler implements AuthenticationFailureHandler {
private String loginIdName;
private String loginPwdName;
private String errorMsgName;
private String defaultFailureUrl;
@Inject
private LoginService loginService;
@Override
public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse res,
org.springframework.security.core.AuthenticationException exception)
throws IOException, ServletException {
// 로그인 정보 저장
String userName = req.getParameter(loginIdName);
String password = req.getParameter(loginPwdName);
req.setAttribute(loginIdName, userName);
req.setAttribute(loginPwdName, password);
// 에러 메세지 저장
// String errorMsg = exception.getMessage();
// req.setAttribute(errormsgname, errorMsg);
String errorMsg = null;
if (exception instanceof BadCredentialsException) {
loginFailure(userName);
errorMsg = MessageUtils.getMessage("error.BadCredentials");
} else if (exception instanceof InternalAuthenticationServiceException) {
errorMsg = MessageUtils.getMessage("error.BadCredentials");
} else if (exception instanceof DisabledException) {
errorMsg = MessageUtils.getMessage("error.Disaled");
} else if (exception instanceof CredentialsExpiredException) {
errorMsg = MessageUtils.getMessage("error.CredentialsExpired");
}
req.setAttribute(errorMsgName, errorMsg);
req.getRequestDispatcher(this.defaultFailureUrl).forward(req, res);
}
protected void loginFailure(String username) {
loginService.loginFailCount(username);
int count = loginService.checkFailCount(username);
if(count == 3) {
loginService.disabledUser(username);
}
}
public String getLoginIdName() {
return loginIdName;
}
public void setLoginIdName(String loginIdName) {
this.loginIdName = loginIdName;
}
public String getLoginPwdName() {
return loginPwdName;
}
public void setLoginPwdName(String loginPwdName) {
this.loginPwdName = loginPwdName;
}
public String getErrorMsgName() {
return errorMsgName;
}
public void setErrorMsgName(String errorMsgName) {
this.errorMsgName = errorMsgName;
}
public String getDefaultFailureUrl() {
return defaultFailureUrl;
}
public void setDefaultFailureUrl(String defaultFailureUrl) {
this.defaultFailureUrl = defaultFailureUrl;
}
public LoginService getLoginService() {
return loginService;
}
public void setLoginService(LoginService loginService) {
this.loginService = loginService;
}
}
에러에 따라서 에러에 맞는 예외 메세지를 전송해야 합니다.
스프링에서 제공하는 예외 명칭
명칭 |
설명 |
BadCredentialException |
비밀번호가 일치하지 않은 경우 |
InternalAuthenticationServiceException |
시스템 문제로 내부 인증 관련 처리 요청을 할 수 없는 경우 |
AthenticationCredentialNotFoundException |
인증 요구가 거부 됐을 경우 |
LockedException |
인증 거부 : 잠긴 계정일 경우 |
DisabledException |
인증 거부 : 계정 비활성화 |
AccountExpiredException |
인증 거부 : 계정 유효 기간 만료 |
CredentialExpiredException |
인증 거부 : 비밀번호 유효 기간 만료 |
login.xml
<update id="disabledUser" parameterType="java.lang.String">
update login_info
set
enabled = '0'
where user_id = #{username}
</update>
<update id="loginFailCount" parameterType="java.lang.String">
update login_info
set
fail_count = fail_count +1
where user_id = #{username}
</update>
<select id="checkFailCount" parameterType="java.lang.String"
resultType="java.lang.Integer">
select
fail_count
from login_info
where user_id = #{username}
</select>
LoginTest.java
//@RunWith(JUnitParamsRunner.class)
@RunWith(SpringJUnit4ClassRunner.class)
@WebAppConfiguration
@ContextConfiguration(locations="file:src/main/webapp/WEB-INF/spring/**/**.xml")
public class LoginTest {
private final Logger logger = LoggerFactory.getLogger(LoginTest.class);
@Inject
private LoginService loginService;
// private WebApplicationContext wac;
// private MockMvc mockMvc;
@Before
public void setUp() {
// this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build();
}
/*@Test
@Parameters({
"test, $2a$10$U23dLUDB9ABFXCfK0PO6kukpXIG.gwHHguAmvUKLYEjYgvGvsTgRu"
})
public void loginTest_로그인_실패시_카운팅이_증가하는지_확인(String user_id, String password)
throws Exception{
logger.error(user_id);
logger.error(password);
// mockMvc.perform(post("/login").params(params))
loginService.loginFailCount(user_id);
}*/
@Test
public void loginTest_로그인_실패시_카운팅이_증가하는지_확인() throws Exception{
String user_id = "test";
String password = "$2a$10$U23dLUDB9ABFXCfK0PO6kukpXIG.gwHHguAmvUKLYEjYgvGvsTgRu";
loginService.loginFailCount(user_id);
int count = loginService.checkFailCount(user_id);
loginService.disabledUser(user_id);
logger.info(String.valueOf(count));
// mockMvc.perform(post("/login").params(params))
}
}
JUnitParamsRunner.class를 사용해보려고 했는데 LoginService를 찾지 못하여 실패했습니다.
그래서 일반적인 단위 테스트를 했습니다.
반응형
'개발(합니다) > Java&Spring' 카테고리의 다른 글
Spring 유효성 검사(hibernate) (0) | 2019.01.23 |
---|---|
Spring Security 정리 (5) : 로그인 성공 후 처리 (0) | 2019.01.21 |
Spring에서 메세지 처리하기 (0) | 2019.01.18 |
Java HashMap 정렬하기 (0) | 2019.01.18 |
Spring Security 정리(3) : https (0) | 2019.01.17 |