01-31 06:56
Notice
Recent Posts
Recent Comments
Link
«   2025/01   »
1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30 31
Archives
관리 메뉴

기록을 합시다.

[Spring] 개인프로젝트-1- 자체 회원가입 구현하기 본문

공부/Java

[Spring] 개인프로젝트-1- 자체 회원가입 구현하기

울집고양이세마리 2023. 5. 18. 03:35

설정

spring boot 버전 : 3.0.6

dependency 설정

dependencies {
    implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
    annotationProcessor 'org.projectlombok:lombok'
    compileOnly 'org.projectlombok:lombok'
    developmentOnly 'org.springframework.boot:spring-boot-devtools'
    //spring security
    implementation 'org.springframework.boot:spring-boot-starter-security'

    //jwt
    implementation 'io.jsonwebtoken:jjwt-api:0.11.2'
    runtimeOnly 'io.jsonwebtoken:jjwt-impl:0.11.2'
    runtimeOnly 'io.jsonwebtoken:jjwt-jackson:0.11.2'

    implementation 'org.springframework.boot:spring-boot-starter-web'
    implementation 'org.springframework.boot:spring-boot-starter-thymeleaf'
    runtimeOnly 'com.h2database:h2'
    runtimeOnly 'org.mariadb.jdbc:mariadb-java-client'
    annotationProcessor 'org.projectlombok:lombok'
    providedRuntime 'org.springframework.boot:spring-boot-starter-tomcat'
    testImplementation 'org.springframework.boot:spring-boot-starter-test'
}

application.properties 설정

# MariaDB
spring.datasource.url=jdbc:mariadb://localhost:3306/aparttalk
spring.datasource.username=데이터베이스 유저 이름
spring.datasource.password=데이터베이스 유저의 비밀번호

# Hibernate
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
spring.jpa.properties.hibernate.dialect=org.hibernate.dialect.MariaDB103Dialect

# Spring dev-tools
livereload.enabled=true
freemarker.cache=false

#thymeleaf
spring.thymeleaf.enabled=true
spring.thymeleaf.cache=false
spring.thymeleaf.prefix=classpath:/templates/
spring.thymeleaf.suffix=.html

User.java

package com.example.aparttalk.user.model;

import jakarta.persistence.*;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Entity
@Table(name = "user")
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @Column(nullable = false)
    private String userId;

    @Column(nullable = false)
    private String email;

    @Column(nullable=false)
    private String userName;

    @Column(nullable=false)
    private String password;

    @Column
    private Long apartId;

    @Column(nullable=false)
    private Boolean isVerified;

    @Column
    private String file;

    @Column
    private String Role;

    public Long getId(){
        return id;
    }
}

컬럼으로는 id, userid, email, username, password, apartId, isVerified, file, Role이 있다.

  • id : 유저의 고유 아이디
  • userid : 유저가 로그인 할 때 사용할 아이디
  • username : 유저가 커뮤니티에서 사용할 닉네임
  • email : 유저가 비밀번호 같은 것을 잃어버렸을 때 유용하게 사용할 이메일
  • password : 유저가 로그인 할 때 사용할 비밀번호
  • apartId : 유저가 소속되어있는 아파트
  • isVerified : 유저가 아파트에 소속 되어있는지 아닌지
  • file : 유저가 올릴 아파트 고지서(아파트 입주민 인증용)
  • Role : 단순히 사용자인지, 아니면 관리자인지 

UserRepository.java

package com.example.aparttalk.user.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import com.example.aparttalk.user.model.User;

public interface UserRepository extends JpaRepository<User, Long> {}

UserRepositor를 만들어서 JpaRepository를 상속 받도록 했다. 상속받음으로써 User 인스턴스를 DB에 저장하고 등등 하는 CRUD 기능을 이용할 수 있다.

UserService.java

package com.example.aparttalk.user.service;

import com.example.aparttalk.user.dto.UserDTO;
import com.example.aparttalk.user.model.User;
import com.example.aparttalk.user.repository.UserRepository;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    private BCryptPasswordEncoder passwordEncoder;
    private final UserRepository userRepository;

    public UserService(UserRepository userRepository) {
        this.userRepository = userRepository;
    }

    public UserDTO createUser(UserDTO userDTO){
        // 유저 생성 => userId, email, userName,
        // password를 받고, isVerified는 False로, apart_id도 아직 할당 못 받음

        //password 암호화
        String password = userDTO.getPassword();
        String encodedPassword = passwordEncoder.encode(password);

        //apart_id => 없음, isVerified => False(아직 인증 못 받아서)
        userDTO.setPassword(encodedPassword);
        userDTO.setIsVerified(Boolean.FALSE);
        userDTO.setRole("ROLE_USER");

        User user = User.builder()
                .userId(userDTO.getUserId())
                .email(userDTO.getEmail())
                .password(userDTO.getPassword())
                .userName(userDTO.getUserName())
                .apartId(userDTO.getApartId())
                .isVerified(userDTO.getIsVerified())
                .Role(userDTO.getRole())
                .build();

        user = userRepository.save(user);

        return UserDTO.builder()
                .userId(user.getUserId())
                .email(user.getEmail())
                .userName(user.getUserName())
                .isVerified(user.getIsVerified())
                .Role(user.getRole())
                .build();
    }

    public Boolean checkUser(UserDTO userDTO){
        User user = userRepository.findByEmail(userDTO.getEmail());

        if(user == null){
            return Boolean.TRUE;
        }else{
            return Boolean.FALSE;
        }
    }
}

UserService라는 클래스를 만들어서 사용자 관련 로직을 처리하도록 했다. 

  • createUser:  UserDTO 객체를 받아와서 새로운 사용자를 생성하도록 했다. 먼저 입력받은 비밀번호를 암호화한 후, User객체를 생성해서 UserRepository를 통해 저장했다. 저장된 사용자 정보를 다시 UserDTO로 변환하여 반환했다.(근데 굳이 반환 안 해도 될 듯..)

UserController.java

package com.example.aparttalk.user.controller;

import com.example.aparttalk.user.dto.UserDTO;
import com.example.aparttalk.user.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

@Controller
public class UserController {
    @Autowired
    private UserService userService;

    @GetMapping("/signup")
    public void getSignUp(){
    }

    @PostMapping("/signup")
    public void postSignUp(UserDTO userDTO, Model model) {
        try{
            System.out.println("UserService"+userDTO.getUserName()+userDTO.getUserId()+userDTO.getEmail());
            userService.createUser(userDTO);
        } catch(Exception e){
            System.out.println(e);
        }
    }
    
    @GetMapping("/id-check")
    public void idCheck(@RequestParam UserDTO userDTO, Model model){
        if (userService.checkUser(userDTO)){
            model.addAttribute("message", "Y");
        }else{
            model.addAttribute("message", "N");
        }
    }
}

컨트롤러에서는 회원가입, id-check를 해준다. 

  • public void getSignUp() : "/signup" URL에 대한 GET 요청이 들어오면 뷰(View)를 반환한다.
  • public void postSignUp(UserDTO userDTO, Model model) : "/signup" URL에 대한 POST 요청이 들어오면, UserDTO를 생성하여 `UserService`의 `createUser` 메소드를 호출한다.
  • public void idCheck(@RequestParam UserDTO userDTO, Model model) : "/id-check" URL에 대한 GET 요청이 들어오면, UserDTO를 생성하여 `UserService`의 `checkUser` 메소드를 호출한다. 이 때 @RequestParam`어노테이션은 HTTP 요청 파라미터로부터 값을 받아온다.

WebSecurityConfig.java

package com.example.aparttalk.user.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.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig {
    @Bean
    public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
        http.csrf().disable()
                .authorizeHttpRequests((authz) -> authz
                .requestMatchers("/user/**").hasRole("USER")
                .requestMatchers("/admin/**").hasRole("ADMIN")
                                .requestMatchers("/signup").permitAll()
                                .requestMatchers("/signin").permitAll()
                                .requestMatchers("/css/**").permitAll()
                .anyRequest().authenticated()
                );
        return http.build();
    }
    
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

참고로, 최근에는 antMatchers가 사라지고, 그 대신에 requestMathcers를 사용한다고 한다.

아마 조금 옛날 포스트들에는 다 antMatchers를 사용하고 있어서 따라 치다가 오류가 나서 뭔가 이상하다고 생각되어 그냥 홈페이지 들어가서 찾아봤다...

 

Configuration Migrations :: Spring Security

In 6.0, @Configuration is removed from @EnableWebSecurity, @EnableMethodSecurity, @EnableGlobalMethodSecurity, and @EnableGlobalAuthentication. To prepare for this, wherever you are using one of these annotations, you may need to add @Configuration. For ex

docs.spring.io

결과 

잘 된다!! 

 

이제 자바스크립트 상으로 fetch해서 아이디 체크, 이메일 체크 및 input 값들 검증만 해주면 된다. ㅜㅜ

Comments