Programming/Spring

Spring - API 인증 (http, 고정 인증 로그인 구현)

잇(IT) 2023. 10. 4. 18:48

- Resolver를 사용 할 때 파라미터로 인증 토큰을 받게 되면 값이 중복 될 수 있기 때문에 header를 통해 받는 것이 좋다.

.......

@Override
    public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, WebDataBinderFactory binderFactory) throws Exception {
        String accessToken = webRequest.getHeader("Authorization");
        if (accessToken == null || accessToken.equals("")) {
            throw new Unauthorized();
        }

        //데이터베이스 사용자 확인 작업

        return new UserSession(1L);
    }

1. NativeWebRequest를 통해 HTTP 요청에 대한 여러 값을 받을 수 있고, webRequest.getHeader를 통해 Header 속성 중 Authorization의 값을 받을 수 있다.

2. Header의 Authorization 값을 accessToken으로 받고, accessToken의 조건을 통과하면 UserSession의 객체를 생성한다.


- intellij에서 http

- intellj에서 post.http와 같이 http 파일을 생성하게 되면 특정 경로로 요청했을 때 결과 값을 확인 할 수 있다.

 

- post.http

### 테스트 요청

GET http://localhost:8080/test2
Content-Type: application/json
Authorization: as


- 고정 인증 로그인 구현

- 인증을 구현하기 위해선 먼저 로그인 기능을 구현해야 한다.

 

- 로그인 관련 Controller를 생성

 

- Member.java

@Entity
@NoArgsConstructor(access = AccessLevel.PROTECTED)
@ToString
@Getter
public class Member {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    private String email;

    private String password;

    private LocalDateTime createdAt;

}

1. 사용자 데이터를 저장할 테이블을 생성하기 위해 Member Entity를 생성한다.

2. @ToString, @Getter를 통해 반환 타입이 Member일 경우 JSON 형태로 body에 값을 담아 전달 할 수 있다.

 

- MemberRepository.java

public interface MemberRepository extends CrudRepository<Member, Long> {

    Optional<Member> findByEmailAndPassword(String email, String password);
}

1. 새로운 Member Entity를 DB 작업하기 위한 Repository를 생성한다.

2. CrudRepository는 기본적은 CRUD를 제공한다.

3. JPA를 사용하기 때문에 findByEmailAndPassword와 같이 특정 명령어 + 엔티티를 메서드 명으로 지정하여 쿼리를 생성할 수 있다.


* @Entity를 통해 테이블 생성 시 데이터 추가하는 방법

 

- data.sql

INSERT INTO `member` (name, email, password, created_at) VALUES ('백인수','saymay10@naver.com','1234','2023-10-04')

- @Entity를 통해 테이블 생성 시 해당 테이블에 날릴 쿼리를 위와 같이 sql 파일을 통해 작성한다.

 

- application.yml

spring:
......

  jpa:
    defer-datasource-initialization: true

  sql:
    init-model: always
    
......

- yml 파일에 위와 같이 jpa, sql 설정을 추가한다.

 

- 위 두개의 설정을 마치게 되면 엔티티 생성 시 해당 쿼리가 테이블에 실행되어 데이터가 저장된다.


- AuthController.java

@Slf4j
@RestController
@RequiredArgsConstructor
public class AuthController {

    private final MemberRepository memberRepository;

    @PostMapping("/auth/login")
    public Member login(@RequestBody Login login){
        //json 아이디/비밀번호
        log.info(">>>login={}", login);
        //DB에서 조회
        Member member = memberRepository.findByEmailAndPassword(login.getEmail(), login.getPassword())
                .orElseThrow(InvalidSigninInformation::new);
        //토큰을 응답
        return member;
    }
}

1. 로그인 위한 Controller를 새롭게 생성한다. 위 코드는 DB에 저장되어 있는 Email, Password가 존재하면 Member 객체를 생성하고 해당 객체를 반환한다.

 

- test 코드

@SpringBootTest
@AutoConfigureMockMvc
public class MemberControllerTest {

    @Autowired
    private ObjectMapper objectMapper;
    @Autowired
    private MockMvc mockMvc;
    @Autowired
    private MemberRepository memberRepository;

    @Test
    @DisplayName("auth test")
    public void test1() throws Exception {

        Login login = new Login();
        login.setEmail("saymay10@naver.com");
        login.setPassword("1234");
//        Member member = memberRepository.findByEmailAndPassword(login.getEmail(), login.getPassword())
//                .orElseThrow(InvalidSigninInformation::new);

        mockMvc.perform(MockMvcRequestBuilders.post("/auth/login")
                .contentType(MediaType.APPLICATION_JSON)
                .content(objectMapper.writeValueAsString(login)))
                .andExpect(status().isOk())
                .andDo(print());
    }
}

728x90