출처: https://bumcrush.tistory.com/182 [맑음때때로 여름]

로그인폼과 회원가입폼 HTML

더보기

로그인폼과 회원가입폼

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>로그인 페이지</title>
</head>
<body>
    <h1>로그인 페이지</h1>
<hr>
 <form action="/login" method="POST">
     <input type="text" name="username" placeholder="UserName"/><br/>
     <input type="password" name="password" placeholder="Password"/><br/>
     <button>로그인</button>
 </form>

<a href = "/joinForm">회원가입을 아직 않으셨나요?</a>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>회원가입 페이지</title>
</head>
<body>
<h1>회원가입 페이지</h1>
<form action="/join" method="POST">
    <input type="text" name="username" placeholder="UserName"/><br/>
    <input type="password" name="password" placeholder="Password"/><br/>
    <input type="email" name="email" placeholder="Email"/><br/>
    <button>회원가입</button>
</form>

</body>
</html>

 

[ 회원가입 Contoller ]

  @PostMapping("/join")
    public String join(User user){

        System.out.println(user);


        // 2. 패스워드 암호화를 추가해줌 securityConfig에도 BcryptpasswordEncoder를 @Bean으로 등록
        String rawPassword = user.getPassword();
        String encPassword = bCryptPasswordEncoder.encode(rawPassword);
        user.setPassword(encPassword);

        
        // 1. userRepository.save(user); // 회원가입 잘됨. 비밀번호 : 1234 => 시큐리티로 로그인을 할수 없음,
        // :: 패스워드가 암호화가 안되었기 때문
        user.setRole("ROLE_USER");
        userRepository.save(user);


        return "redirect:/loginForm";
    }

[ USER MODEL ]

package com.cos.security1.model;

import lombok.Data;
import org.hibernate.annotations.CreationTimestamp;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import java.sql.Timestamp;

@Entity
@Data
public class User {

    @Id // primary Key
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private  int id;
    private String username;
    private String password;
    private String email;
    private String role; // ROLE_USEr, ROLE_ADMIN
    @CreationTimestamp
    private Timestamp createdate;

}

 

[ USER REPORSITORY - JPA ]

package com.cos.security1.repository;

import com.cos.security1.model.User;
import org.springframework.data.jpa.repository.JpaRepository;


// CRUD 함수를 JPArepository가 들고 있음
// @Repository라는 어노테이션이 없어도 Ioc가 됨 (자동 빈등록)
// -> JpaRepository를 상속했기 때문
public interface UserRepository extends JpaRepository<User, Integer> {


    // findBy규칙 -> username 문법
    // seelct * from user where username = #{username}
    public User findByUsername(String username);
}

 

[ config 수정 ]

밑 두줄 추가.

 


public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {

        http.csrf().disable(); // /login으로 갈때 스프링 시큐리티가 낚아채지 않도록

        http.authorizeRequests()
                .antMatchers("/user/**").authenticated()
                .antMatchers("/manager/**").access("hasRole('ROLE_ADMIN') or hasRole('ROLE_MANAGER')")
                .antMatchers("/admin/**").access("hasRole('ROLE_ADMIN')")
                .anyRequest().permitAll()// 다른주소는 OK
                .and()
                .formLogin()
                .loginPage("/loginForm") // 로그인안햇을때 403페이지가 뜨는게 아니라 login페이지를 뜨게만들어줌
                .loginProcessingUrl("/login") //login 주소가 호출이 되면 시큐리티가 낚아채서 대신 로그인을 진행
                .defaultSuccessUrl("/"); // 로그인이 완료되면 이동할 주소


    }

 

 

[ userDetails를 상속하는 클래스 생성 ]

유저정보를 저장.

package com.cos.security1.config.auth;

// 시큐리티가 /login 주소 요청이 오면 낚아채서 로그인을 진행시킴
// 로그인 진행이 완료되면 seisson을 만들어줌 (Security ContextHolder)
// 세션에 들어갈 수 있는 정보(오브젝트) > authentication 타입의 객체
// authentication 안에 User정보가 있어야 함.
// user 오브젝트 타입 > UserDetails 타입 객체

// Security Session => Authentication => UserDetails(PrincipalDetails)

import com.cos.security1.model.User;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;

import java.util.ArrayList;
import java.util.Collection;

public class PrincipalDetails implements UserDetails {

    private User user; // 콤포지션

    public PrincipalDetails(User user){
        this.user = user;
    }


    // 해당 user의 권한을 리턴하는 곳
    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        Collection<GrantedAuthority> collect = new ArrayList<>();
        collect.add(new GrantedAuthority() {
            @Override
            public String getAuthority() {
                return user.getRole();
            }
        });
        return collect;
    }

    @Override
    public String getPassword() {
        return user.getPassword();
    }

    @Override
    public String getUsername() {
        return user.getUsername();
    }


    // 계정 만료
    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    // 계정 잠김
    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    // 계정 유효기간
    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    // 계정 정지
    @Override
    public boolean isEnabled() {

        // ex) 휴면계정
        // 현재시간 - 로그인시간 => 1년초과하면 return false

        return true;
    }
}

 

[ userDetailsService를 상속한 클래스 만들기 ]

이름 그대로 유저의 정보를 저장해주는 서비스

// 시큐리티 설정에서 loginProcessingUrl("/login")
// /login 요청이 오면 자동으로 UserDetailsService 타입으로 ioc되어있는 loadUserByUsername가 함수 실행
package com.cos.security1.config.auth;

import com.cos.security1.model.User;
import com.cos.security1.repository.UserRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;


// 시큐리티 설정에서 loginProcessingUrl("/login")
// /login 요청이 오면 자동으로 UserDetailsService 타입으로 ioc되어있는 loadUserByUsername가 함수 실행

@Service
public class PrincaipalDetailsService implements UserDetailsService{


    @Autowired
    private UserRepository userRepository;

    // 시큐리티 session > authentication > userDetails(principalDetails)
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        // html에 꼭 "username"으로 해야함 (String username)과 매칭이 안됨
        // 바꾸고 싶다면 security config에 .usernameParameter("username2")
        // 그냥 username을 쓰자 ^^

        User userEntity = userRepository.findByUsername(username);
        if(userEntity != null){
            return new PrincipalDetails(userEntity);
        }

        return null;
    }
}

[ userRepository 에는 유저의 정보를 조회하는 부분 추가 ]

    // findBy규칙 -> username 문법
    // seelct * from user where username = #{username}
    public User findByUsername(String username);

 

+ Recent posts