반응형

우선 스프링 시큐리티를 사용하기 위해 

 

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
  <groupId>org.springframework.security</groupId>
  <artifactId>spring-security-test</artifactId>
  <scope>test</scope>
</dependency>

 

디펜던시를 추가해 주자 

이렇게 하면 스프링 시큐리티를 쓸 준비는 끝난다 

이제 회원가입을 위해 User Table과 User Model 을 생성해보자

 

이런식으로 추가 해줬다.

그후 

 

package com.seogi.myhome.model;

import lombok.Data;

import javax.persistence.*;
import java.util.ArrayList;
import java.util.List;

@Entity
@Data
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    private String username;
    private String password;
    private boolean enabled;

이렇게 모델 객체를 생성해준다. 

 

그 후 config 패키지를 생성을 해주고 

WebSecurityConfig를 만들어준다. 

https://www.baeldung.com/spring-security-jdbc-authentication

 

Spring Security: Exploring JDBC Authentication | Baeldung

Explore the capabilities offered by Spring to perform JDBC Authentication using an existing DataSource configuration.

www.baeldung.com

사이트는 이곳을 참고 하였다. 

 

package com.seogi.myhome.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.provisioning.InMemoryUserDetailsManager;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Autowired
    private DataSource dataSource;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/" , "/account/register","/css/**" ).permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .loginPage("/account/login")
                .permitAll()
                .and()
                .logout()
                .permitAll();
    }
    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth)
            throws Exception {
        auth.jdbcAuthentication()
                .dataSource(dataSource)
                .passwordEncoder(passwordEncoder()) // 비밀번호를 암호화 하는 작업
                // 인증처리
                .usersByUsernameQuery("select username,password,enabled "
                        + "from user "
                        + "where username = ?")
                // 권한처리
                .authoritiesByUsernameQuery("select u.username,r.name "
                        + "from user_role ur inner join user u on  ur.user_id = u.id "
                        + "inner join role r on ur.role_id = r.id "
                        + "where u.username = ?");
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
}

이렇게 추가해준다. 

이렇게 할 경우에 antMatchers 에 인증처리가 없어도 접속할 수있는

페이지를 설정해주고 

loginPage는 login api를 설정해준다.ㅣ 

 

그후 PasswordEndcoder를 설정하여 회원가입을 할때 

비밀번호를 단반향으로 암호화에 필요한 걸 빈등록을해준다. 

 

그 후 configureGlobal을 하나 만들어준다. 

인증 처리에 관한 데이터 소스를 처리해준다.

이곳에 대해서는 나중에 many to many로 다대다 조인을 할 것이다. 

 

그 후 role 테이블을 만들어 이곳에는 인증에 대한 테이블이다

조인에 필요한 테이블을 생성해 준다.

 

테이블을 생성해 주었다면 모델 객체도 만들어주자

 

package com.seogi.myhome.model;

import lombok.Data;

import javax.persistence.*;
import java.util.List;

@Entity
@Data
public class Role {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;
    private String name;

부트스트랩에서 로그인 페이지 샘플을 가져온다.

 

https://getbootstrap.com/docs/4.6/examples/

 

Examples

Quickly get a project started with any of our examples ranging from using parts of the framework to custom components and layouts.

getbootstrap.com

컨트롤러를 만들어 주어 로그인 페이지에 접근할 수 있도록 만들어준다. 

 

@GetMapping("/login")
public String loing(){
    return "account/login";
}

그 후 타임리프 th:if로 

<div th:if="${param.error}" class="alert alert-danger" role="alert">
    Invalid username and password.
</div>

</div>
<div th:if="${param.logout}" class="alert alert-light" role="alert">
    로그아웃 되었습니다.
</div>

에러를 처리해준다. 

 

이렇게 처리 되었다. 

 

그 후 로그인을 위해 회원가입 페이지를 만들어야겠다. 

회원가입 페이지는 간단하게 로그인 페이지를 카피하여 살짝 수정하여 재활용 하자 

 

페이지까지 만들었다면 

@ManyToMany 설정해준다. 

 

@ManyToMany
@JoinTable( name = "user_role", joinColumns = @JoinColumn(name = "user_id"),
inverseJoinColumns = @JoinColumn(name = "role_id")) // 조인될 상대 테이블을 적어준다.
private List<Role> roles = new ArrayList<>();
@ManyToMany(mappedBy = "roles")
private List<User> users;

이렇게 모델 객체에 추가하여준다. 

으로 조인해준다.


그 후 UserRepository를 만들어준다. 

 

package com.seogi.myhome.repository;

import com.seogi.myhome.model.Board;
import com.seogi.myhome.model.User;
import org.springframework.data.jpa.repository.JpaRepository;

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

 

JPA를 쓸 준비는 끝낫다. 

 

이제 컨트롤러를 작성해주자 

 

@GetMapping ("/register")
public String register(){
    return "account/register";
}

으로 접속 할 수있게 해주고 

그 후 서비스를 작성해주자

 

package com.seogi.myhome.service;

import com.seogi.myhome.model.Role;
import com.seogi.myhome.model.User;
import com.seogi.myhome.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

@Service
public class UserService {

    @Autowired
    private UserRepository userRepository;
    @Autowired
    private PasswordEncoder passwordEncoder;

        public User save(User user){
            String encodedPassword = passwordEncoder.encode(user.getPassword());
            user.setPassword(encodedPassword);
            user.setEnabled(true);
            Role role = new Role();
            role.setId(1);
            user.getRoles().add(role);
            return userRepository.save(user);
        }


}

서비스에서는 Repositoy를 사용하기 위해 

AutoWired로 추가해 준뒤 

아까 빈 등록을 해준 비밀번호 단방향 암호화를 해줄

@Autowired
private PasswordEncoder passwordEncoder;

이 두개를 AutoWired로 추가 해준다. 

 

Save()라는 메소드를 작성해준다. 

먼저 파라미터로 비밀번호를 받아와 passwordencoder로 암호화를 해준뒤 

유저 권한인 setEnabled를 true를 바꿔준다. 

그후 Role 객체를 추가 해준다. 

1번으로 설정 해준다. 

 

1번은 Role_user 로 권한을 설정해준다.

 

그후 

private List<Role> roles = new ArrayList<>();

아까 모델객체에서 추가해준 roles 를 ArrayList로 바꿔준다.

 

@PostMapping("/register")
public String register(User user){
    userService.save(user);
    return "redirect:/";
}

이제 컨트롤러를 완성시켜준다. 

 

<form class="form-signin" th:action="@{/account/register}" method="post">

    <a th:href="@{/}"><img  class="mb-4" src="https://getbootstrap.com/docs/4.6/assets/brand/bootstrap-solid.svg" alt="" width="72" height="72"></a>


    <h1 class="h3 mb-3 font-weight-normal">회원가입</h1>
    <label for="username" class="sr-only">UserName</label>
    <input type="text" id="username" class="form-control"  name="username"  required autofocus>
    <label for="inputPassword" class="sr-only">Password</label>
    <input type="password" id="inputPassword" class="form-control" name="password" required>
    <div class="checkbox mb-3">
    </div>
    <button class="btn btn-lg btn-primary btn-block" type="submit">Sign in</button>
    <p class="mt-5 mb-3 text-muted">&copy; 2017-2021</p>
</form>

 

이제 회원가입을 하면

 

이렇게 단방향으로 암호화가 되었다! 

 

잘 안된다면 아래의 소스코드를 확인해보자! 

 

 

https://github.com/MoonSeokHyun?tab=repositories 

 

MoonSeokHyun - Overview

http://mls0000.dothome.co.kr/. MoonSeokHyun has 7 repositories available. Follow their code on GitHub.

github.com

 

반응형

+ Recent posts