1. pom.xml에 dependency 추가
- jjwt maven
- spring security
<!-- https://mvnrepository.com/artifact/io.jsonwebtoken/jjwt -->
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-security -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2. 기본패키지에 WebSecurityConfigurerAdapter를 상속하는
SecurityConfig클래스 생성
@RequiredArgsConstructor
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter{
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.cors() // cors에 대해 감시하겠음.
.and()
.csrf().disable() // frontend와 backend가 분리된 상황에서는 일반적으로 csrf감시를 안 함.
.sessionManagement() // session: 전통적인 로그인 지원방식으로 서버에 인증자에 대한 정보를 저장함.
.sessionCreationPolicy(SessionCreationPolicy.STATELESS) // 전통적인 로그인 방식이 아니므로 session을 생성하지 않음.
.and()
.authorizeRequests() // 요청에 대해 인증을 하도록 함.
.antMatchers("/","/api/auth/**").permitAll() // /와 /api/auth/로 시작하는 요청은 프리패스
.anyRequest() // 그 외의 요청에 대해서는
.authenticated(); // 인증을 완료했을 때만 이용 가능.
}
// 나중에 비밀번호 암호화나
// 로그인 시 입력한 암호화 db에 저장된 암호가 일치하는지 확인할 때 사용함.
public PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
3. TokenProvider 클래스 생성
@Component // 객체화 하기위해 선언
public class TokenProvider {
private static final String SECRET_KEY="dsaf1313eaf"; // 비밀키: 아무거나 길게 작성
public String create(MemberEntity memberEntity) {
// 지금으로부터 1시간 후의 값이 expire에 들어감.
Date expire = Date.from(Instant.now().plus(1, ChronoUnit.HOURS));
return Jwts.builder()
.signWith(SignatureAlgorithm.HS512, SECRET_KEY) // 헤더+페이로드+비밀키를 이용해 암호화할 때 HS512알고리즘 사용
.setSubject(memberEntity.getId())// 토큰 작성자의 아이디: username은 외부에 노츨되어 있어 노출되지 않은 id 사용
.setIssuer("bmsapi") // 토큰이 사용될 앱
.setIssuedAt(new Date()) // 토큰이 생성된 시각
.setExpiration(expire) // 토큰이 만료되는 시각
.compact(); // build()가 아니라 compact()함수를 이용해서 문자열 객체를 만듦.
}
}
4. MemberService에 login메서드 생성
@Autowired
private TokenProvider tokenProvider;
@Autowired
private PasswordEncoder passwordEncoder; // 나중에 사용
// 나중에 비밀번호를 암호화하면, username과 password를 동시 인증이 불가능
// 따라서 동시에 넣어 인증하지 않고 해당 회원이 있는지 여부만 확인
public MemberDTO login(MemberDTO dto) {
MemberEntity member = getByCredentials(dto.getUsername());
if(member == null) {
throw new RuntimeException("해당 회원이 없어서 로그인 거부");
}
// 입력받은 비밀번호와 db에 저장된 비밀번호가 일치하는지 확인
// 나중에 비밀번호를 암호화하면 여기서 passwordEncoder.match()메서드를 이용한다.
if(!member.getPassword().equals(dto.getPassword())) {
throw new RuntimeException("비밀번호가 안 맞아서 로그인 거부");
}
String token = tokenProvider.create(member);
dto = new ModelMapper().map(member, MemberDTO.class);
dto.setToken(token);; // MemberDTO에 private String token; 추가
return dto;
}
-------------------------------------------------------------------------------
public MemberEntity getByCredentials(String username) {
return memberRepository.findByUsername(username);
}
5. AuthController 생성
- MemberController의 insert핸들러를 잘라내어 붙여넣기
-> 인증없이 insert작업이 가능
- login핸들러 생성(PostMapping)
@RestController
@RequestMapping("/api/auth")
public class AuthController {
@Autowired
public MemberService memberService;
@PostMapping("/login")
public ResponseEntity<?> login(@RequestBody MemberDTO dto){
Map<String, Object> map = new HashMap<>();
if(dto == null) {
map.put("result", "잘못된 데이터");
return ResponseEntity.badRequest().body(map);
}
if(dto.getUsername() == null || dto.getUsername().equals("")) {
map.put("result", "잘못된 데이터");
return ResponseEntity.badRequest().body(map);
}
if(dto.getPassword() == null || dto.getPassword().equals("")) {
map.put("result", "잘못된 데이터");
return ResponseEntity.badRequest().body(map);
}
try {
dto = memberService.login(dto);
map.put("result", dto);
return ResponseEntity.ok().body(map);
} catch (Exception e) {
e.printStackTrace();
map.put("result", "로그인 실패");
return ResponseEntity.badRequest().body(map);
}
}
@PostMapping("/insert")
public ResponseEntity<?> insert(@RequestBody MemberDTO dto){
Map<String, Object> map = new HashMap<>();
if(dto == null) {
map.put("result", "잘못된 데이터");
return ResponseEntity.badRequest().body(map);
}
if(dto.getUsername() == null) {
map.put("result", "잘못된 데이터");
return ResponseEntity.badRequest().body(map);
}
if(dto.getName() == null) {
map.put("result", "잘못된 데이터");
return ResponseEntity.badRequest().body(map);
}
if(dto.getPassword() == null) {
map.put("result", "잘못된 데이터");
return ResponseEntity.badRequest().body(map);
}
if(dto.getPassword2() == null) {
map.put("result", "잘못된 데이터");
return ResponseEntity.badRequest().body(map);
}
if(!(dto.getPassword().equals(dto.getPassword2()))) {
map.put("result", "잘못된 데이터");
return ResponseEntity.badRequest().body(map);
}
try {
dto = memberService.insert(dto);
map.put("result", dto);
return ResponseEntity.ok().body(map);
} catch (Exception e) {
e.printStackTrace();
map.put("result", "입력 실패");
return ResponseEntity.badRequest().body(map);
}
}
}
6. vscode에서 MemberInsert.js 수정
insertFetchfn("member", dto);
--->
insertFetchfn("auth", dto);
- NetworkUtils.js에서 insertFetchfn 수정
export function insertFetchfn(servicename, dto){
return fetchFn("POST", `http://localhost:9005/api/${servicename}`, dto)
.then(data =>{
console.log(data.result);
if(servicename === "auth"){
servicename = "member";
}
let what = "data.result.id";
if(servicename === "member"){
what = data.result.username;
}
window.location.href = `/${servicename}/detail/${what}`;
})
}
'React' 카테고리의 다른 글
bmsapi 프로젝트 - bmsfront 리액트 2 (board 패키지) (0) | 2023.04.24 |
---|---|
bmsapi 프로젝트 - bmsfront 리액트 (member 패키지) (0) | 2023.04.24 |
smsapi 프로젝트 - smsfront 리액트 (0) | 2023.04.21 |
imsapi 프로젝트 - imsfront 리액트 (0) | 2023.04.20 |
State (0) | 2023.04.18 |