🏆 2024

맛집 분야 크리에이터

🏆 2023

IT 분야 크리에이터

👩‍❤️‍👨 구독자 수

182

✒️ 게시글 수

0
https://tistory1.daumcdn.net/tistory/4631271/skin/images/blank.png 네이버블로그

🩷 방문자 추이

오늘

어제

전체

🏆 인기글 순위

티스토리 뷰

728x90
반응형

 

https://tistory1.daumcdn.net/tistory/4631271/skin/images/blank.png

 

 

먼저, 로그인 페이지를 만들어줍니다.

컨트롤러에 로그인 페이지를 생성해주세요.

// Controller
@RequestMapping("/login")
public String login() throws Exception {
    return "login";
}

 

 

연결된 로그인 html파일에는 다음과 같이 "username"과 "password"가 있어야 합니다.

method는 무조건 post여야하구요!!

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Login</title>
</head>
<body>
    <h2>Login</h2>
    <form action="/login" method="post">
    	<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
        <label for="username">Username:</label>
        <input type="text" id="username" name="username" required><br>
        <label for="password">Password:</label>
        <input type="password" id="password" name="password" required><br>
        <!-- input fields for username and password -->
    	<button type="submit">Login</button>
</form>
</body>
</html>

 

 

 

이제 로그인페이지를 통해 로그인한 사용자의 ID를 토대로 DB에서 사용자권한정보를 가져와야합니다.

이 부분은 spring security를 이용합니다.

spring security를 pom.xml에 추가해줍니다.

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

 

 

반응형

 

그리고 DB 사용자정보 테이블에서 사용자ID를 토대로 사용자정보를 가져오는 UserService를 만들어놓습니다.

사용자가 로그인페이지에서 로그인 시, 로그인한 USER_ID를 토대로 권한을 가져오는 서비스입니다.

// ID -> 사용자정보 조회
public List<UserDTO> getUserInfo(String USER_ID)throws Exception {
    return UserDAO.getUserInfo(USER_ID);
}

 

 

이제 사용자가 로그인 시, 사용자권한정보를 가져오는 UserDetailsService를 만듭니다.

사용자가 로그인버튼을 누르면 loadUserByUsername이 실행됩니다.

저는 비밀번호없이 로그인하게끔 만들어놓았기에 비밀번호는 "1111"로 고정해놓았습니다.

userDetails = builder.username(userInfo.get(0).getUser_id()) <- 이부분에서 사용자권한정보를 가져오면 됩니다.

 

import java.util.List;

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.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;

import dto.UserDTO;
import service.UserService;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
	
	@Autowired
	private UserService userService;

	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		UserDetails userDetails = null;
		System.out.println(username); 
		List<UserDTO> userInfo;
		try {
			userInfo = userService.getUserInfo(username);
			PasswordEncoder encoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
			
			org.springframework.security.core.userdetails.User.UserBuilder builder =
						org.springframework.security.core.userdetails.User.builder().passwordEncoder(encoder::encode);
					
			if (userInfo.size() > 0) {
				userDetails = builder.username(userInfo.get(0).getUser_id())
						.password("1111") // 비밀번호 없음
						.roles(userInfo.get(0).getAuth())
						.build();
			}else {
            	// 계정정보가 없는 경우
	            throw new UsernameNotFoundException("User not found with username: " + username);
	        }
		} catch (Exception e) {
			System.out.println(e);
			throw new UsernameNotFoundException("Exception occurred while loading user by username", e);
	    }
		
		return userDetails;
	}

}

 

 

728x90

 

마지막으로 spring security의 configuration을 만들어줍니다.

CORS설정 이라고 주석처리되어있는 부분을 삽입하지 않으면 로그인버튼을 눌러도 302에러가 뜨면서 계속 GET으로만 요청이 들어오더라구요. CORS 설정을 꼭 넣어주세요.

 

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.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

import javax.sql.DataSource;

@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserDetailsServiceImpl userDetailsService;

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth
            .userDetailsService(userDetailsService)
            .passwordEncoder(passwordEncoder());
    }

	//CORS 설정
    @Bean
    public CorsConfigurationSource corsConfigurationSource() {
        CorsConfiguration config = new CorsConfiguration();

        config.setAllowCredentials(true);
        config.setAllowedOrigins(Arrays.asList("http://localhost:80"));
        config.setAllowedMethods(Arrays.asList("HEAD","POST","GET","DELETE","PUT"));
        config.setAllowedHeaders(Arrays.asList("*"));

        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        source.registerCorsConfiguration("/**", config);
        return source;
    }
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
	        .httpBasic().disable()
	        .cors().configurationSource(corsConfigurationSource())
	        .and()
            .authorizeRequests()
                .antMatchers("/login").permitAll()
                .anyRequest().authenticated()
                .and()
            .formLogin()
                .loginPage("/login")
                .permitAll()
                .defaultSuccessUrl("/", true) // 로그인 성공 시 "/"로 리다이렉트
                .and()
            .logout()
                .permitAll();
        http.csrf().disable();
        http.headers().frameOptions().disable();
        
    }
    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }
}

 

 

 

이제 로그인페이지에서 로그인 버튼을 누르면, UserDetailsServiceImpl에서 출력해놓았던

System.out.println(username); <- 요부분이 콘솔창에 출력되고, 사용자권한별로 페이지접속이 가능해집니다.

 

이제 권한별 페이지접속 설정을 해봅니다.

SecurityConfig파일에서 페이지 접속을 설정하는 부분입니다.

권한별 URL을 설정해주면 됩니다.

   
.antMatchers("/login", "/css/**", "/js/**",  "/font/**", "/images/**").permitAll() // "/" 및 스태틱자원들의 경로는 모두에게 허용
    .antMatchers("/manage/**").hasRole("ADMIN") // ADMIN 권한 필요
    .anyRequest().authenticated() // 그 외의 리소스는 인증된 사용자만 허용

 

 

 

- 컨트롤러에서 사용자ID, 권한정보 가져오는 방법

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
// 사용자 ID
String USER_ID = authentication.getName();
// 권한정보
String Authority = authentication.getAuthorities();

 

 

 

로그아웃기능에 대해서는 아래 링크를 눌러주세요

 

[java] spring security 로그아웃기능 만들기 (+자동로그아웃)

https://domdom.tistory.com/660

 

[java] spring security 로그아웃기능 만들기 (+자동로그아웃)

예전에 spring security로 로그인, 사용자권한별 페이지접속에 대해서 글을 적은적이 있는데요. 이번에는 로그아웃 기능을 만들고, 아래와 같이 3가지 기능을 추가해보려고 합니다. 1. 로그아웃버튼

domdom.tistory.com

 

728x90
반응형
댓글

돔돔이님의
글이 좋았다면 응원을 보내주세요!