Springboot/블로그만들기

[Springboot] 블로그 만들기 (22)_스프링 시큐리티(3)_커스터마이징

21종 2023. 11. 28. 17:55

커스터마이징하기 전에 코드수정을 하자

인증이 안된 사용자들은 /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();
	}
}

 

테스트

내가 만든 로그인 폼으로 잘 넘어온다.

 


참고 유튜브 (메타코딩님 강의)

https://youtu.be/Ny44L9R0oEk?si=3GqVG3p-yHu0-gUP