SpringBoot 는 SpringSecurity 와 함께 자동 로그 인 기능 을 실현 하 는 코드 입 니 다.
11394 단어 SpringBootSpringSecurity자동 로그 인
많은 사이트 에서 우 리 는 로그 인 할 때 비슷 한 옵션 을 볼 수 있다.왜냐하면 항상 사용자 에 게 사용자 이름 비밀 번 호 를 입력 하 게 하 는 것 은 매우 번 거 로 운 일이 기 때문이다.
자동 로그 인 기능 은 사용자 가 로그 인 에 성공 한 후에 특정한 시간 동안 사용자 가 브 라 우 저 를 닫 고 다시 열 거나 서버 가 다시 시작 되면 사용자 가 다시 로그 인 할 필요 가 없 으 며 사용 자 는 인터페이스 데 이 터 를 직접 방문 할 수 있다 는 것 이다.
흔히 볼 수 있 는 기능 으로서 우리 의 Spring Security 도 해당 하 는 지 지 를 제 공 했 을 것 이다.본 고 는 Spring Security 에서 이 기능 을 어떻게 실현 하 는 지 살 펴 보 자.
1.remember-me 가입
설정 편 의 를 위해 두 개의 의존 도 를 추가 하면 됩 니 다.
설정 클래스 에 다음 코드 를 추가 합 니 다:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("yolo")
.password("123").roles("admin");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.rememberMe()
.and()
.csrf().disable();
}
}
보시 다시 피 여기 하나.rememberMe()
만 추가 하면 자동 로그 인 기능 이 성공 적 으로 추 가 됩 니 다.다음 에 우 리 는 마음대로 테스트 인 터 페 이 스 를 추가 합 니 다.
@RestController
public class HelloController {
@GetMapping("/hello")
public String hello(){
return "Hello Yolo !!!";
}
}
이 럴 때 기본 로그 인 페이지 에 옵션 이 하나 더 생 겼 습 니 다.바로 저 를 기억 하 는 것 입 니 다.우 리 는 사용자 이름 비밀 번 호 를 입력 하고 이 상 자 를 기억 하고 로그 인 단 추 를 누 르 면 로그 인 작업 을 수행 합 니 다.
로그 인 데이터 에는 username 과 password 외 에 도 remember-me 가 있 습 니 다.이 를 보 여 주 는 이 유 는 로그 인 페이지 를 사용자 정의 할 필요 가 있다 면 Remember Me 라 는 옵션 의 key 를 어떻게 써 야 하 는 지 알려 드 리 려 는 것 입 니 다.
로그 인 에 성공 하면 자동 으로 hello 인터페이스 로 넘 어 갑 니 다.시스템 이 hello 인 터 페 이 스 를 방문 할 때 가지 고 있 는 쿠키:
여러분,여기 하나 더
remember-me
가 생 겼 습 니 다.이것 이 바로 여기 서 실현 하 는 핵심 입 니 다.이것remember-me
에 대해 제 가 잠시 후에 설명 하 겠 습 니 다.저희 가 먼저 효 과 를 테스트 하 겠 습 니 다.다음은 브 라 우 저 를 닫 고 브 라 우 저 를 다시 엽 니 다.정상 적 인 상황 에서 브 라 우 저 를 닫 고 다시 엽 니 다.hello 인 터 페 이 스 를 다시 방문 하려 면 다시 로그 인 해 야 합 니 다.그러나 이때 우 리 는 hello 인 터 페 이 스 를 다시 방문 한 결과 다시 로그 인 하지 않 아 도 바로 접근 할 수 있다 는 것 을 알 게 되 었 습 니 다.이것 은 우리 의 Remember Me 설정 이 효력 이 발생 한 다 는 것 을 설명 합 니 다(즉,다음 자동 로그 인 기능 이 효력 이 발생 합 니 다).
원리 분석
이치 대로 말 하면 브 라 우 저 를 닫 고 다시 켜 면 다시 로그 인 해 야 하 는데 지금 은 기다 릴 필요 가 없다.그렇다면 이 기능 은 어떻게 이 루어 진 것 일 까?
먼저 쿠키 에 많이 나 오 는 이것
remember-me
을 분석 해 보 겠 습 니 다.이 값 은 딱 봐 도 Base 64 코드 를 바 꾼 문자열 입 니 다.저 희 는 인터넷 에 있 는 온라인 도 구 를 사용 하여 디 코딩 할 수 있 고 두 줄 의 코드 를 간단하게 써 서 디 코딩 할 수 있 습 니 다.
@Test
void contextLoads() {
String s = new String(
Base64.getDecoder().decode("eW9sbzoxNjAxNDczNTY2NTA1OjlmMGY5YjBjOTAzYmNjYmU3ZjMwYWM0NjVlZjEzNmQ5"));
System.out.println("s = " + s);
}
이 코드 를 실행 하면 출력 결 과 는 다음 과 같 습 니 다.s = yolo:1601473566505:9f0f9b0c903bccbe7f30ac465ef136d9
이 Base 64 문자열 은 실제
:
로 구분 되 어 세 부분 으로 나 뉘 어 있 음 을 알 수 있 습 니 다.(1)첫 번 째 단 계 는 사용자 이름 이 므 로 의심 할 필요 가 없습니다.
(2)두 번 째 단 계 는 시간 스탬프 로 보 입 니 다.우 리 는 온라인 도구 나 자바 코드 를 통 해 분석 한 결과 이것 은 2 주 후의 데이터 입 니 다.
(3)세 번 째 단락 에서 저 는 뜸 을 들 이지 않 겠 습 니 다.이것 은 MD5 해시 함 수 를 사용 하여 계산 한 값 입 니 다.그의 명문 형식 은?
username + ":" + tokenExpiryTime + ":" + password + ":" + key
마지막 키 는 해시 소금 값 으로 영패 가 수정 되 는 것 을 예방 할 수 있 습 니 다.쿠키
remember-me
의 의 미 를 알 게 된 후에 저 희 는 제 로그 인 절 차 를 기억 하 는 것 에 대해 서도 쉽게 알 수 있 습 니 다.브 라 우 저 를 닫 은 후에 다시 열 면 사용 자 는 hello 인 터 페 이 스 를 방문 합 니 다.이때 쿠키 에 있 는
remember-me
을 가지 고 서버 에 갑 니 다.서 비 스 를 받 은 후에 사용자 이름과 만 료 시간 을 편리 하 게 계산 한 다음 에 사용자 이름 에 따라 사용자 비밀 번 호 를 조회 한 다음 에 MD5 해시 함 수 를 통 해 해시 값 을 계산 할 수 있 습 니 다.계 산 된 해시 값 과 브 라 우 저가 전달 하 는 해시 값 을 비교 하면 이 토 큰 이 효과 가 있 는 지 확인 할 수 있 습 니 다.절 차 는 바로 이런 절차 이다.그 다음 에 우 리 는 소스 코드 를 분석 함으로써 이 절차 가 맞 는 지 검증 해 보 자.
3.소스 코드 분석
이어서 우 리 는 소스 코드 를 통 해 우리 가 위 에서 말 한 것 이 맞 는 지 검증 해 보 자.
여기 서 주로 두 가지 측면 에서 소개 합 니 다.하 나 는 remember-me 라 는 영패 가 생 성 되 는 과정 이 고 다른 하 나 는 이 를 분석 하 는 과정 입 니 다.
1.생 성
생 성의 핵심 처리 방법 은 다음 과 같다.
TokenBasedRememberMeServices#onLoginSuccess:
@Override
public void onLoginSuccess(HttpServletRequest request, HttpServletResponse response,
Authentication successfulAuthentication) {
String username = retrieveUserName(successfulAuthentication);
String password = retrievePassword(successfulAuthentication);
if (!StringUtils.hasLength(password)) {
UserDetails user = getUserDetailsService().loadUserByUsername(username);
password = user.getPassword();
}
int tokenLifetime = calculateLoginLifetime(request, successfulAuthentication);
long expiryTime = System.currentTimeMillis();
expiryTime += 1000L * (tokenLifetime < 0 ? TWO_WEEKS_S : tokenLifetime);
String signatureValue = makeTokenSignature(expiryTime, username, password);
setCookie(new String[] { username, Long.toString(expiryTime), signatureValue },
tokenLifetime, request, response);
}
protected String makeTokenSignature(long tokenExpiryTime, String username,
String password) {
String data = username + ":" + tokenExpiryTime + ":" + password + ":" + getKey();
MessageDigest digest;
digest = MessageDigest.getInstance("MD5");
return new String(Hex.encode(digest.digest(data.getBytes())));
}
(1)먼저 로그 인 에 성공 한 Authentication 에서 사용자 이름/비밀 번 호 를 추출 합 니 다.(2)로그 인 에 성공 하면 비밀번호 가 지 워 질 수 있 으 므 로 처음부터 비밀 번 호 를 받 지 못 하면 UserDetails Service 에서 사용 자 를 다시 불 러 오고 비밀 번 호 를 다시 가 져 옵 니 다.
(3)그 다음 에 토 큰 의 유효기간 을 가 져 옵 니 다.토 큰 의 유효기간 은 기본적으로 2 주 입 니 다.
(4)그 다음 에
makeTokenSignature
방법 으로 해시 값 을 계산 합 니 다.사실은 username,토 큰 유효기간 과 password,key 에 따라 해시 값 을 계산 합 니 다.이 키 를 설정 하지 않 았 다 면 기본 값 은RememberMeConfigurer#getKey
방법 에서 설정 되 었 습 니 다.값 은 UUID 문자열 입 니 다.(5)마지막 으로 사용자 이름,영패 유효기간 및 계 산 된 해시 값 을 쿠키 에 넣 습 니 다.
네 번 째 시 에 대해 서 다시 한 번 말씀 드 리 겠 습 니 다.
키 를 설정 하지 않 았 기 때문에 키 의 기본 값 은 UUID 문자열 입 니 다.서버 에서 다시 시작 하면 키 가 변 합 니 다.그러면 이전에 보 낸 모든
remember-me
자동 로그 인 토 큰 이 효력 을 잃 기 때문에 이 키 를 지정 할 수 있 습 니 다.지정 한 방식 은 다음 과 같 습 니 다.
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.anyRequest().authenticated()
.and()
.formLogin()
.and()
.rememberMe()
.key("yolo")
.and()
.csrf().disable();
}
키 를 설정 하면 서버 가 다시 시작 하 더 라 도 브 라 우 저 를 열 고 닫 아 도 hello 인터페이스 에 접근 할 수 있 습 니 다.이것 은 remember-me 영패 가 생 성 되 는 과정 입 니 다.어떻게 onLogin Success 방법 에 이 르 렀 는 지 에 대해 서 는 아 이 디 어 를 살짝 알려 드릴 수 있 습 니 다.
AbstractAuthenticationProcessingFilter#doFilter -> AbstractAuthenticationProcessingFilter#successfulAuthentication -> AbstractRememberMeServices#loginSuccess -> TokenBasedRememberMeServices#onLoginSuccess。
2.해석
그렇다면 사용자 가 브 라 우 저 를 끄 고 열 면
/hello
인 터 페 이 스 를 다시 방문 합 니 다.이때 인증 절 차 는 어 떻 습 니까?우리 가 전에 말 했 듯 이 Spring Security 의 일련의 기능 은 모두 하나의 필터 체인 을 통 해 이 루어 진 것 이다.
RememberMe
이 기능 도 물론 예외 가 아니다.Spring Security 에서
RememberMeAuthenticationFilter
관련 일 을 전문 적 으로 하 는 방법 을 제 공 했 습 니 다.RememberMeAuthenticationFilter
의doFilter
방법 을 살 펴 보 겠 습 니 다.
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
HttpServletResponse response = (HttpServletResponse) res;
if (SecurityContextHolder.getContext().getAuthentication() == null) {
Authentication rememberMeAuth = rememberMeServices.autoLogin(request,
response);
if (rememberMeAuth != null) {
rememberMeAuth = authenticationManager.authenticate(rememberMeAuth);
SecurityContextHolder.getContext().setAuthentication(rememberMeAuth);
onSuccessfulAuthentication(request, response, rememberMeAuth);
if (this.eventPublisher != null) {
eventPublisher
.publishEvent(new InteractiveAuthenticationSuccessEvent(
SecurityContextHolder.getContext()
.getAuthentication(), this.getClass()));
}
if (successHandler != null) {
successHandler.onAuthenticationSuccess(request, response,
rememberMeAuth);
return;
}
}
chain.doFilter(request, response);
}
else {
chain.doFilter(request, response);
}
}
이 방법 에서 가장 중요 한 것 은SecurityContextHolder
에서 현재 로그 인 사용자 인 스 턴 스 를 얻 을 수 없다 면rememberMeServices.autoLogin
논리 로 로그 인 하 는 것 입 니 다.이 방법 을 살 펴 보 겠 습 니 다.
public final Authentication autoLogin(HttpServletRequest request,
HttpServletResponse response) {
String rememberMeCookie = extractRememberMeCookie(request);
if (rememberMeCookie == null) {
return null;
}
logger.debug("Remember-me cookie detected");
if (rememberMeCookie.length() == 0) {
logger.debug("Cookie was empty");
cancelCookie(request, response);
return null;
}
UserDetails user = null;
try {
String[] cookieTokens = decodeCookie(rememberMeCookie);
user = processAutoLoginCookie(cookieTokens, request, response);
userDetailsChecker.check(user);
logger.debug("Remember-me cookie accepted");
return createSuccessfulAuthentication(request, user);
}
catch (CookieTheftException cte) {
throw cte;
}
cancelCookie(request, response);
return null;
}
이 를 통 해 알 수 있 듯 이 여 기 는cookie
정 보 를 추출 하고cookie
정 보 를 디 코딩 한 다음 에processAutoLoginCookie
방법 으로 검 사 를 하 는 것 입 니 다.processAutoLoginCookie
방법의 코드 는 붙 이지 않 겠 습 니 다.핵심 절 차 는 먼저 사용자 이름과 만 료 시간 을 얻 은 다음 에 사용자 이름 에 따라 사용자 비밀 번 호 를 조회 한 다음 에 MD5 해시 함 수 를 통 해 해시 값 을 계산 하 는 것 입 니 다.받 은 해시 값 과 브 라 우 저가 전달 한 해시 값 을 비교 하면 이 영패 가 효과 가 있 는 지 확인 하고 로그 인 이 효과 가 있 는 지 확인 할 수 있 습 니 다.3.총화
위의 글 을 보면 우리 가
RememberMe
기능 을 켜 면 가장 핵심 적 인 것 은cookie
에 놓 인 토 큰 이라는 것 을 알 수 있 을 것 이다.이 토 큰 은session
의 제한 을 돌파 했다.서버 가 재 부팅 되 더 라 도 브 라 우 저 를 닫 고 다시 열 어도 이 토 큰 이 기한 이 지나 지 않 으 면 데 이 터 를 방문 할 수 있다.토 큰 을 잃 어 버 리 면 다른 사람 이 이 토 큰 을 들 고 우리 시스템 에 마음대로 로그 인 할 수 있 습 니 다.이것 은 매우 위험한 조작 입 니 다.
그러나 실제 적 으로 이것 은 역설 이다.사용자 체험(적은 로그 인)을 향상 시 키 기 위해 우리 시스템 은 안전 문 제 를 피 할 수 없 지만 우 리 는 기술 을 통 해 안전 위험 을 최소 화 할 수 있다.
SpringBoot 가 SpringSecurity 와 함께 자동 로그 인 기능 을 수행 하 는 코드 에 관 한 이 글 은 여기까지 소개 되 었 습 니 다.더 많은 SpringSecurity 자동 로그 인 내용 은 저희 의 이전 글 을 검색 하거나 아래 의 관련 글 을 계속 읽 어 주시 기 바 랍 니 다.앞으로 도 많은 응원 부탁드립니다!
이 내용에 흥미가 있습니까?
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
【Java・SpringBoot・Thymeleaf】 에러 메세지를 구현(SpringBoot 어플리케이션 실천편 3)로그인하여 사용자 목록을 표시하는 응용 프로그램을 만들고, Spring에서의 개발에 대해 공부하겠습니다 🌟 마지막 데이터 바인딩에 계속 바인딩 실패 시 오류 메시지를 구현합니다. 마지막 기사🌟 src/main/res...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.