비밀번호 암호화

2024. 8. 14. 14:01Springboot-React

build.gradle dependencies 에 다음 문구 추가

implementation 'org.springframework.boot:spring-boot-starter-security'

 

이후 SecurityConfig 작성

 

package com.kh.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.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

//보안 설정
//보안 기능을 사용하기 위해선 build.gradle에 security를 상속해야함
@Configuration
@EnableWebSecurity
public class SecurityConfig {

    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
        http // 모든 http 메서드 요청 허용
            .authorizeHttpRequests(authorize -> authorize
                .anyRequest().permitAll() // -> 비밀번호 없이 포트에 들어갈 수 있도록 연결 허용
            )
            // 3000 포트나 외부에서 오는 보호 비활성화
            .csrf(csrf -> csrf.disable());
        
        // http.build : 위의 작성한 상세내용 통합
        return http.build();
    }

    //패스워드 관련 객체 생성
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

 

** BCryptPasswordEncoder

- BCryptPasswordEncoder -> 주의 : 이 이름으로 객체 생성하면 안됨
- Blowfish 암호 알고리즘 기반
- Crypt : Encrypt의 준말
- Encoder : 데이터를 특정 방식으로 변환하는 역할

BCUser(dto)

Mapper.java, Mapper.xml를 안만들고 자동으로 sql 구문을 생성하는 방식 사용.

package com.kh.dto;

import jakarta.persistence.Entity;
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.NoArgsConstructor;
import lombok.Setter;

@Entity //mysql과 매핑
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
public class BCUser {

	@Id //기본키
	@GeneratedValue(strategy = GenerationType.IDENTITY) //자동으로 올라가는 시퀀스
	private int id;
	private String username;
	private String email;
	private String password;
}

 

이후 repository 패키지를 따로 파서 BCUserRepository 클래스 생성

사실상 안에 아무것도 입력하지 않음

package com.kh.repository;

import org.springframework.data.jpa.repository.JpaRepository;

import com.kh.dto.BCUser;

// mybatis와 mapper를 생략해서 작성하는 방법
// JpaRepository : sql문을 알아서 작성해줌
public interface BCUserRepository extends JpaRepository<BCUser, Integer>{
	//save, select로 무언가를 특정하여 검색하는 행동을 하지 않는 한 기본적인 sql 작성 할 필요 없음
	//BCUser saveUser();
	
	//이메일 찾기 기능 예시
	//sql문이 알아서 완성됨 (select * from BCUser ~~)
	//BCUser findByEmail(String email);
}

 

BCUserService

package com.kh.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import com.kh.dto.BCUser;
import com.kh.mapper.BCUserMapper;
import com.kh.repository.BCUserRepository;

@Service
public class BCUserService {
	

	@Autowired
	private BCUserRepository repository;

	@Autowired
	private PasswordEncoder pwEncoder;
	
	
	//패스워드 인코드를 저장
	public void saveUser(BCUser user) {
		user.setPassword(pwEncoder.encode(user.getPassword())); // 한 번 암호화된 암호를 가져옴
		
		//jpaRepository 안에 save가 이미 저장되어 있기 때문에 굳이 메서드를 작성할 필요 없음
		repository.save(user);	
	}
	
	

}

 

이후 Controller는 하던대로 작성

package com.kh.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;

import com.kh.dto.BCUser;
import com.kh.service.BCUserService;


@RestController
public class BCController {

	@Autowired
	private BCUserService userService;
	
	@PostMapping("/api/register")
	public String saveUser(@RequestBody BCUser user) {
		System.out.println(user);
		userService.saveUser(user);
		return "회원가입 성공";
	}
	
}

 

 

이제 리액트 파트

 

import './App.css';
import {useState} from 'react';
import axios from 'axios';

function App() {
  const [username, setUsername] = useState("");
  const [password, setPassword] = useState("");
  const [email, setEmail] = useState("");

  const handleSubmit = () => {
    //formData : 기본적으로 multipart 형식. -> 이미지를 쓴다는 전제 조건이 있음
    const formData = new FormData();
    
    formData.append('username', username);
    formData.append('password', password);
    formData.append('email', email);
    
    axios.post("http://localhost:9012/api/register", formData, {
      headers : {'Content-Type' : 'application/json'},
      params: {
        username : username,
        password : password,
        email : email
      }
    })
    .then(res => {
      alert("회원가입 완료");
    })
    
    setUsername('');
    setPassword('');
    setEmail('');
  }
  return (
    <div className="App">
      <h2>회원가입</h2>
      <form>
        <label> 닉네임 : 
          <input value={username} onChange={(e) => setUsername(e.target.value)}/>
        </label>
        <label> 비밀번호 : 
          <input value={password} onChange={(e) => setPassword(e.target.value)}/>
        </label>
        <label> 이메일 : 
          <input value={email} onChange={(e) => setEmail(e.target.value)}/>
        </label>
        <button onClick={handleSubmit}>가입하기</button>
      </form>
    </div>
  );
}

export default App;

 

여기서 axios와 fetch 두 개를 다 해본다면 다음과 같다

//axios
axios.post("http://localhost:9012/api/register", formData, {
  headers : {'Content-Type' : 'application/json'},
  params: {
    username : username,
    password : password,
    email : email
  }
})
.then(res => {
  alert("회원가입 완료");
})


const user = {
  username : username,
  email : email,
  password : password
}

//fetch
fetch("http://localhost:9012/api/register", {
  method: "post",
  headers : {'Content-Type' : 'application/json'},
  //body : formData -> multipart로 보내게 됨
  body : JSON.stringify(user)
})
.then((res) => {
  res.text();
})
.then(data => {
  alert('회원가입 완료');
})
.catch(err => {
  alert('회원가입 실패');
})

 

개인적으로는 axios가 더 편해서 axios로 진행.

 

이제 시현

폼에 입력

 

DB에 들어옴. 비밀번호 암호화 성공

'Springboot-React' 카테고리의 다른 글

상세화면 만들기 + css  (0) 2024.08.21
주소 api  (0) 2024.08.16
네이버 로그인 3  (0) 2024.08.13
프로필 사진 올리기 2  (1) 2024.08.09
프로필 사진 올리기 1  (0) 2024.08.09