비밀번호 암호화
2024. 8. 14. 14:01ㆍSpringboot-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로 진행.
이제 시현
'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 |