요즘 알고리즘 ps 위주로 공부하다가, 갑자기 또 개발 흥미가 생겨 간단하게 개인프로젝트를 진행중이다.
급하게 임팩트있게 만드려는 것이 아닌, 개인공부를 위해서 오랫동안 조금씩 꾸준히 만들어볼 생각이다.
대략 생각중인 TodoList는 아래와 같다.
Todo List (~22.04.11)
1. 로그인 / 로그아웃 thymeleaf 좀 더 손보기
2. 게시판 기능 (포스트, 댓글, 대댓글)
3. 소셜로그인 기능
4. RestTemplate을 이용한 회원 티어 자동 표시하기 (단, ROLE_GUEST는 제외)
5. 웹소켓을 이용한 댓글알림 기능
6. 채팅방 기능 구현
목표나 다짐은 아래 포스팅에서 볼 수 있다.
https://kth990303.tistory.com/125
이번 포스팅에는 1. 로그인 / 로그아웃 thymeleaf 관련 기능에 대해 적어보려 한다.
전체 코드는 아래 깃허브 주소를 클릭하면 볼 수 있다.
https://github.com/kth990303/BOJStudyList
디렉토리 구조
member 도메인 안에 config를 설정해두었는데,
이후에 프로젝트 바로 밑(member 도메인 밖)으로 수정할 수도 있다.
그리고 salt 디렉토리는 필요없으므로 무시하면 된다.
Spring Security를 이용하기 위한 환경설정
build.gradle에 아래 디펜던시를 추가해주자.
// spring security
implementation 'org.springframework.boot:spring-boot-starter-security'
implementation 'org.thymeleaf.extras:thymeleaf-extras-springsecurity5'
testImplementation 'org.springframework.security:spring-security-test'
나는 따로 리액트나 뷰를 사용하지 않고 템플릿엔진인 Thymeleaf를 사용하기 때문에
thymeleaf-springsecurity 디펜던시를 추가해주었다.
또한, 테스트 코드에서 스프링 시큐리티 테스트를 진행할 수 있도록 spring-security-test 디펜던시를 추가해주었다.
application.properties는 아래와 같이 작성했다/
spring.datasource.username=[MySQL 아이디]
spring.datasource.url=jdbc:mysql://localhost:3306/[schema이름]?characterEncoding=UTF-8&serverTimezone=UTC
spring.datasource.password=[MySQL 비밀번호]
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
MySQL 기본 포트번호가 3306이다.
또한, ddl-auto = update로 진행할 경우엔, DB table에 변경사항이 생기는 코드 수정이 있을 때 바로바로 적용된다.
이 때의 변경사항이란, 새로운 데이터가 추가되는 이런게 아닌, 아예 테이블 하나가 새로 생성되거나, 테이블 연관관계가 바뀌거나 하는 것을 말한다.
Spring Security를 이용하기 위해선 Config를 설정해주어야 한다.
WebSecurityConfigureAdapter를 상속받는 SecurityConfig 클래스 코드를 만들어주자.
SecurityConfig.java
@EnableWebSecurity
@RequiredArgsConstructor
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
private final MemberService memberService;
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**", "/js/**", "/img/**");
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//.csrf().disable()// 나중에 없애기
.authorizeRequests()
.antMatchers("/", "/createMemberForm", "/login", "/errorPage", "/index").permitAll()
.antMatchers("/editMember").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/")
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
;
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(memberService)
.passwordEncoder(new BCryptPasswordEncoder());
}
}
@EnableWebSecurity 는 spring security를 사용가능하게 하는 어노테이션이다. 반드시 붙여주어야한다.
@RequiredArgsConstructor는 스프링 기본 어노테이션으로, final 필드변수들을 파라미터로 받는 생성자를 만들어준다.
여기서는 spring security 인증을 member에 관해서 진행하는 로그인 기능이기 때문에 MemberService를 받아준다.
@Configuration을 붙일 경우, 스프링 빈으로 등록된다.
이제 void configure 메소드를 설정해줄 차례인데, 오버로딩으로 인해 같은 메소드가 3개나 있는 것을 확인할 수 있다.
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/css/**", "/js/**", "/img/**");
}
web을 띄울 때 인증이나 권한을 요구하지 않는 폴더(또는 파일)를 설정하는 것이다.
web.ignoring()으로 권한을 요구하지 않게 설정해주고, antMatchers로 path를 설정해줄 수 있다.
자세한 기능은 아래 블로그의 포스팅을 참고하자.
https://m.blog.naver.com/kimnx9006/220638156019
이어서 다음 configure 메소드를 보자.
@Override
protected void configure(HttpSecurity http) throws Exception {
http
//.csrf().disable()// 나중에 없애기
.authorizeRequests()
.antMatchers("/", "/createMemberForm", "/login", "/errorPage", "/index").permitAll()
.antMatchers("/editMember").hasRole("ADMIN")
.anyRequest().authenticated()
//로그인
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/")
.permitAll()
//로그아웃
.and()
.logout()
.logoutSuccessUrl("/")
.invalidateHttpSession(true)
;
}
csrf는 보안 관련해서 스프링 시큐리티가 CSRF 공격을 방지해주기 위해 있는 것인데, 소규모 프로젝트에선 크게 문제없기도 하고, csrf().disable()를 해주지 않으면 적절한 처리가 있기 전엔 로그인 로직이 제대로 됨에도 불구하고 튕기기 때문에 이를 무시하는 csrf().disable() 코드를 작성해주어도 크게 문제는 없다. 다만, 보안에는 취약해지는 코드가 되는 것이다.
그러나 thymeleaf의 th:action을 사용하면 자동으로 csrf를 방지해주도록 한다고 한다. (자세히는 모르겠다...)
그래서 csrf().disable()을 해주지 않아도 로그인이 잘 된다는 말씀~
antMatchers에 해당하는 path들에게
.permitAll() : 모든 유저의 접근 허용
.hasRole("ADMIN") : 관리자만 접근 허용
.anyRequest() : 그 외의 path들은
.authenticated : 인증된 (로그인된) 유저만 접근 허용
.and() : 또다른 http 설정을 할 때 사용한다. .and()를 붙이지 않고 http. 으로 진행해도 상관없다.
로그인페이지를 따로 설정해주지 않을경우(또는 그러한 html이 없을 경우) 스프링시큐리티에서 bootstrap css프레임워크로 아주 간단하게 만들은 기본적인 html창의 자체 로그인 html 화면을 자동으로 띄워준다.
로그인을 성공하면 defaultSuccessUrl로 설정된 path로 이동한다.
참고로 이 service 로직은 스프링 시큐리티 내에서 자체적으로 설정해주기 때문에, Service 코드에서 login 구현 코드를 따로 작성하지 않아도 좋다. (물론 추가적으로 기능을 추가하고 싶다면 오버라이딩 or 코드 추가하면 된다.)
로그아웃도 로그인과 마찬가지이다. 맨 마지막에 세션을 invalid화 시켜주는 것을 확인할 수 있다.
환경설정은 모두 마쳤고,
다음에 이어서 도메인과 서비스 로직, 그리고 프론트 thymeleaf 쪽 코드를 포스팅하겠다.
참고 블로그
https://victorydntmd.tistory.com/328
'JAVA > 소박한그룹 프로젝트' 카테고리의 다른 글
[Thymeleaf] 타임리프 Thymeleaf th:style, th:if 사용하기 (0) | 2021.09.14 |
---|---|
[Spring] MapStruct를 이용한 Entity, Dto 반환 및 고찰 (0) | 2021.09.08 |
[Spring] 인텔리제이 디렉토리 구조 변경 중 발생한 Error (0) | 2021.09.08 |
[Spring] Solved API를 이용한 개발에 도움이 되는 글 (0) | 2021.06.09 |
Solvedac API를 이용한 해결한 문제 리스트 만들기 (2) | 2021.06.01 |