커스터마이징하기 전에 코드수정을 하자
인증이 안된 사용자들은 /auth/ ** 이 경로만 허용할거다.
만약 인증이 안된 사용자가 인증이 필요한 경로를 요청할 경우 로그인 페이지로 넘긴다.
header.jsp
로그인과 회원가입은 로그인 하지 않은 사용자가 사용하는 페이지이므로 url에 /auth를 추가한다.
<ul class="navbar-nav">
<li class="nav-item"><a class="nav-link" href="/auth/loginForm">로그인</a></li>
<li class="nav-item"><a class="nav-link" href="/auth/joinForm">회원가입</a></li>
</ul>
UserApiController.java
기존에 사용한 전통적인 로그인 메서드는 삭제
SpringSecurity를 이용한 로그인은 나중에 구현, 지금은 일단 로그인 폼을 띄우는 것 부터 해보자
@PostMapping("/auth/joinProc")
public ResponseDto<Integer> save(@RequestBody User user) { //userName, password, email
System.out.println("UserApiController : save 호출됨");
// 실제로 DB에 insert를 하고 아래에서 return이 되면 된다.
user.setRole(RoleType.USER);
userService.회원가입(user);
return new ResponseDto<Integer>(HttpStatus.OK.value(), 1); // 자바오브젝트를 JSON으로 변환해서 리턴(Jackson)
}
UserController.java
@GetMapping("/auth/joinForm")
public String joinForm() { // 회원가입 폼 띄우는 메서드
return "user/joinForm";
}
@GetMapping("/auth/loginForm")
public String loginForm() { // 로그인 폼 띄우는 메서드
return "user/loginForm";
}
UserService.java
@Transactional // 전체가 성공하면 commit 실패시 rollback
public void 회원가입(User user) {
userRepository.save(user);
}
/* 안쓸꺼임
@Transactional(readOnly = true) // Select 할 때 트랜잭션 시작, 서비스 종료시에 트랜잭션 종료(정합성)
public User 로그인(User user) {
return userRepository.findByUserNameAndPassword(user.getUserName(), user.getPassword());
}
*/
UserRepository.java
public interface UserRepository extends JpaRepository<User, Integer>{
}
loginForm.jsp
<!-- input에 name 추가, button을 Form 내부로 이동, Form action, method 추가 -->
<div class="container">
<form action="#" method="post" >
<div class="form-group">
<label for="userName">UserName</label>
<input type="text" name="userName" class="form-control" placeholder="username" id="username">
</div>
<div class="form-group">
<label for="pwd">Password</label>
<input name="password" type="password" class="form-control" placeholder="password" id="password">
</div>
<div class="form-group form-check">
<label class="form-check-label">
<input name="remember" class="form-check-input" type="checkbox"> Remember me
</label>
</div>
<button id="btn-login" class="btn btn-primary">로그인</button>
</form>
</div>
user.js
/*$("#btn-login").on("click",()=>{ // function(), ()=>{} this 를 바인딩하기 위해서 !!
this.login();
}); // on(이벤트,함수) 이벤트가 발생하면 함수 실행 */
/* ,login: function(){
let data = {
userName : $("#username").val(),
password:$("#password").val(),
};
$.ajax({
type:"POST",
url:"/api/user/login",
data:JSON.stringify(data),
contentType: "application/json; charset=UTF-8",
dataType:"json"
}).done(function(resp){
alert("로그인이 완료되었습니다.");
console.log(resp)
location.href="/";
}).fail(function(error){
alert(JSON.stringify(error));
});
}*/
$.ajax({
// 회원가입 수행 요청
type:"POST",
/*url:"/api/user",*/
url:"/auth/joinProc",
data:JSON.stringify(data),
contentType: "application/json; charset=UTF-8",
dataType:"json"
}).done(function(resp){
alert("회원가입이 완료되었습니다.");
console.log(resp)
location.href="/";
}).fail(function(error){
alert(JSON.stringify(error));
});
SecurityConfig.java 생성
package com.lwj.blog.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
// 빈 등록 : 스프링 컨테이너에서 객체를 관리할 수 있게 하는 것
@Configuration // 빈등록 (IoC관리)
// Controller 에 들어가기전에 여기를 탄다
public class SecurityConfig {
@Bean
SecurityFilterChain configure(HttpSecurity http) throws Exception {
http
.csrf().disable() // csrf 토큰 비활성화 (테스트시 걸어두는게 좋음)
.authorizeRequests()
.antMatchers("/", "/auth/**", "/js/**", "/css/**", "/img/**") // "/auth/**", "/js/**", "/css/**", "/img/**" 에 대해서는
.permitAll() // 모두 허용
.anyRequest() // 다른 request에 대해서는
.authenticated() // 인증이 필요해
.and() // 그리고 인증이 필요한 곳에 대해서는 /auth/loginForm로 url 요청
.formLogin()
.loginPage("/auth/loginForm");
return http.build();
}
}
테스트
내가 만든 로그인 폼으로 잘 넘어온다.