본문 바로가기
✨ Back-end/Spring-Boot

[Spring] 보드게시판 만들기(11) Security 사용해 로그인하기

by 환풍 2023. 4. 21.
728x90
반응형

 

build.gradle

implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity6'
testImplementation 'org.springframework.security:spring-security-test'

SecurityConfig

public WebSecurityCustomizer webSecurityCustomizer() {
        return (web) -> web.ignoring().requestMatchers("/js/**", "/css/**", "/img/**");     
    } 

static 폴더 전체의 내용. ignoring(무시한다.)

 

DB에서 MEM_PW를 암호화 하면

ASDFNJONCUJOQNU(NUN#UNN!@I)#HJ)@!JZXC 와 같이 많은 기호들이 들어가기 때문이다.

board/list에 대해서만 permitAll (허용) 시켜주었기 때문에 해당 패이지에서만 접근이 가능하다.

지금까지는 다른 페이지에 들어가게되면 접근 거부가 뜨게 될 것이다.

 

UserDetailsServiceImpl

UserDetailsSerivceImpl 클래스를 하나 생성해주었다.

이 클래스가 로그인할 때 실행되는 클래스다.
직접 사용하지는 않을 꺼다. SecurityConfig가 얘를 사용한다.

SecurityConfig

얘가 실제로 암호화 시킬 수 있는 클래스다.이 걸 리턴한다.

MemberController 컨트롤러

PasswordEncoer로 미리 만들어진게 실행될 것이다.

MemberController 컨트롤러

회원정보에 있는 회원 비밀번호를 암호화 시켜주겠다.

이렇게하면 완성이지만,

SecurityConfig

여기서 회원가입하러가는 페이지, 하는 페이지 모두 적용되어 엑세스 허용으로 바뀌면서 접근이 가능하게 된다.

 

등록을 하면 엑세스가 거부됬다고 뜬다. 왜냐하면 위 과정을 통해 /member/login으로 가는데 여긴 아직 권한안줬다., 

콘솔에는 회원등록이 정상적으로 된 것을 확인할 수 있다.

DB에 보면 회원 비밀번호가 암호화 되어 있는 것을 확인할 수 있다. 암호화 되어 있지만 pppp의 원래 비밀번호는 1234

기존에 가입되어 있던 qkrwnghd1234와 주홍이안티 아이디는 로그인이 안될 것이다.

 

login.html

input 속성의 name 값으로 memId와 memPw를 가지고 온다.  [ field는 id와 name을 동시에 설정해주는 것이다. ]

또한 여기서 form으로 컨트롤러 /member/login으로 보내주기 때문에 

SecurityConfig

.loginPage("/member/login")

은 로그인 페이지 열리는 url이다.

 

loginProcessingUrl("/loginProcess")
은 로그인이 실제로 진행되는 요청 경로이다. Security가 로그인을 시켜주는 것이다.

login.html

따라서 login.html에서 경로를 loginPorcess로 바꿔주자. login 버튼을 누르면 UserDetailsServiceImpl이 실행된다.

MemberController 컨트롤러

그러면 Post로 받아온 데이터를 전달해주는 여기 컨트롤러에서는 필요 없어지므로

이거는 지워주자.

member-mapper.xml

아이디, 비밀번호, 권한 세 정보를 들고오고, 비밀번호를 가져올 데이터는 필요가 없다. 오른쪽과 같이 수정하자.

MemberService

MemberVO로 매개변수가 들어가있는 것을 memId로 바꿔주었다.

UserDetailsServiceImpl

로그인 요청이 진행되면 UserDetailsServiceImpl이 실행이 된다.

로그인 할 때 필요한 데이터를 전달해줘야한다. UserDetails 자료형으로 감싸서 데이터를 저장할 것이니,

따라서 user로 리턴시켜주면서 Security가 그걸 바탕으로 로그인 해주는 것이다.

SecurityConfig

우선순위에 따라 페이지 경로가 달라지는데, 원래 페이지 경로로 간다. 실패했을때 .defaultSuccessUrl("/member/loginResult") 가 오는건데, 무조건 defaultSuccessUrl로 오고 싶다면 뒤에 true를 넣어준다.

 

MemberController 컨트롤러

failureUrl 경로에 맞게 컨트롤러를 만들어 주었따.

 

기존에 있던 th:block th~~ 로 되어있던 것을 div로 바꿔주었다. 그리고 sec 문법을 사용하기 위해

xmlns:sec="http://www.thymeleaf.org/extras/spring-security" 를 head 전에 html 태그에 함께 넣어주었다.

security에서 사용하는 문법 sec를 코딩해주는데,

isAnonymous() 은 익명유저냐? 묻는 것이다.

FailureHandler

로그인 실패시 어떤 클래스를 상속 받는 클래스를 생성하였다.

SimpleUrlAuthenticationFailureHandler 이라는 클래스를 상속 받는다고 정의하였다.

이후 onAuthenticationFailure 를 선택하여주었다.

FailureHandler

FailureHandler의 객체를 만들어 줘야 onAuthenticationFailure을 실행할 수 있다.

SecurityConfig

로그인 실패시 handler를 생성하여 클래스가 실행된다.

login_result.html

로그인 실패 했을 때 경로를 데이터를 들고 가지 않고, 그냥 가도록 하게끔 다시 설정해놓았다.

header.html

memName 이름은 없으므로 , 

 

.failureHandler() 

 

 

일부로 로그인 실패를 해보았다. 아이디, 비밀번호 모두 없는 데이터들로 넣었다.

콘솔창에 이렇게 userInfo에 정보가 담겨져 있지 않아 로그인 실패 메시지가 뜨게 되었다.

"알 수 없는 이유로 로그인에 실패했습니다." 얘는 

 

그리고 페이지 이동도 제대로 되지 않았다.

FailureHandler

따라서 eMsg라는 변수에 인코딩을 변환해주는 java.net 이라는 URLEncoder를 추가해주었다. 이렇게 넣어주어야 데이터를 가져갈 수 있는 것이다.

"알 수 없는 이유로 로그인에 실패했습니다." 로그인한 정보가 

UserDetailsServiceImpl

아이디를 잘못 넣어주면 조회되는 userInfo 데이터가 없다..

그래서 null이 떨어지므로 로그인 떨어지기 전부터 오류가 나있는 상태이다.

그럼 로그인에 실패하면 다시 로그인 페이지로 오게 된다.

 

 

 강제로 예외를 발생시켜버릴거다.

FaulureHandler

로그인 실패시 페이지 이동에서 컨트롤러 member에 있는 login으로 갈때, eMsg과 함께 isError 데이터를 true로 가져간다.

MemberController 컨트롤러

로그인 실패했을 때만 데이터를 넘겨올 것이기 때문에 @RequestParam(required =false)를 써준다. 

@RequestParam(required =false)은 데이터를 받아도되고 안받아도 될때 써주는 것이다.

이후 Model 객체에 html에서 사용할 수 있게 던져주었다.

FaulureHandler

로그인 페이지 경로 "/member/login" 이걸 이곳에 추가해주면, 

login.html

html에서 받아온 eMsg 값 데이터가 이렇게 출력되는 것을 확인할 수 있다.

 

FailureHandler

FailureHandler 즉, 로그인 실패시 입력한 Id값을 받아오기 위해 login 페이지로 다시 돌아갈 때 추가해주었다.

MemberController 컨트롤러

MemberVO에는 memId 값이 있다.

login.html

컨트롤러에 저장된 memId가 로그인 실패시 다시한번 뜨게된다.

 

header.html

 

${session.userName}으로 바꿔주었다.

 

 

로그인 성공 메시지가 뜨면 지정했던 경로로 잘 이동하는 것을 알 수 있다.

SecurityConfig

로그인 성공하든 실패하든 무조건 loginResult를 갔었다.

로그인 성공했을때 세션 이름 값만 넣고 싶다.

자바로 시큐리티에서 데이터를 뽑아올 것이다.

member-mapper.xml

Service

 

MemberController 컨트롤러

컨트롤러에서 Authentication을 사용해 session 값에 userName 값을 넣어주면서 데이터를 html에 넘겨준다.

성공적으로 userName 값으로 session 데이터에 넣어 조회된 것을 볼 수 있다.


로그아웃을 눌러보자.

header.html

header에서 로그아웃을 눌렀을때 세션을 종료시켜주는 기능도  Security를 이용해 만들어보자.

MemberController 컨트롤러

컨트롤러에서 사용했던 로그아웃 기능은 지워주자.

SecurityConfig

SecurityConfig에서 로그아웃 기능도 만들어주자.

.invalidateHttpSession(true) // 만약에 로그아웃 해버리면 세션데이터 지워버리겠다.

 

로그 아웃을 누르면 정상적으로 로그아웃이 될 것이다.

728x90
반응형

댓글