96일차_SpringBoot

서창민·2023년 8월 1일
0

SpringBoot

목록 보기
5/13
post-thumbnail

23.08.01 96일차

SpringBoot

  • 스프링 부트 시큐리티
1. 인증
- 정상적인 접근인지 비정상적인 접근인지 구분

2. 인가
- 등급에 따른 접근을 제어

EX)
  - 사원 권한
  - 관리자 권한
  - 손님 권한
  • pom.xml
		<!-- security 추가하기 -->
	    <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>

pom.xml에 해당 내용을 추가하여 스프링부트 시큐리티를 사용하도록 선언한다.

  • 프로젝트 만들기

Spring Security를 체크하여 사용하도록 한다.

  • 시큐리티 유저 파일

시큐리티 연결

package com.psd.k4.security;

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.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration
@EnableWebSecurity // 시큐리티에서 사용하는 데 필요한 수많은 객체를 생성한다.
public class SecurityConfig  {

	SecurityConfig(){
		System.out.println("===> 0. SecurityConfig 생성자 확인 ");
	}
	
	@Autowired
	SecurityUserDetailsService  securityUserDetail;

	@Bean
	SecurityFilterChain filterChain( HttpSecurity http ) throws Exception {
		
	    http.authorizeHttpRequests(authorize -> authorize
	              .requestMatchers("/member/**").authenticated()
	              .requestMatchers("/manager/**").hasRole("MANAGER")
	              .requestMatchers("/admin/**").hasRole("ADMIN")
	              .anyRequest().permitAll());
				
		http.csrf().disable();		
		http.formLogin().loginPage("/login.do").defaultSuccessUrl("/loginSuccess.do", true);
		http.exceptionHandling().accessDeniedPage("/accessDenied.do");
		http.logout().invalidateHttpSession(true).logoutSuccessUrl("/");		
		http.userDetailsService(securityUserDetail);
		return http.build(); 
		
	}
	
	@Bean
	PasswordEncoder  passwordEncoder() {		
		return PasswordEncoderFactories.createDelegatingPasswordEncoder();
	}	
	
}

URL에 포함된 권한이 있을시 해당 권한을 불러온다.


시큐리티 유저 (DB에 아이디 패스워드 비교)

package com.psd.k4.security;

import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.User;

import com.psd.k4.login.LoginVO;

//  User 는 폼의 username 과 password 와 자동매칭 진행 
public class SecurityUser  extends  User {
	
	private static final long serialVersionUID = 1L;
	
	// SecurityUserDetailsService 에서 넘어온 table의 username 과 password
	// 를 비교하고 있다고 이해를 하면된다.!!!
	
	public SecurityUser( LoginVO vo ) {
		super(vo.getUsername() , "{noop}"+vo.getPassword(),
			 AuthorityUtils.createAuthorityList(vo.getRole().toString()));
		
		System.out.println("SecurityUser 확인:" + vo.getUsername() + " : " + vo.getPassword());
	}

}

{noop}이 있을떄는 암호화 되지 않은 패스워드를 나타내고,
없을 때에는 암호화된 패스워드를 나타낸다.

(개발시) 하나로 통일해서 사용하는것이 유지보수에 용이하다.

스프링 시큐리티 사용시 하나의 약속이다.


시큐리티 유저 디테일 서비스 (사용자 존재여부)

package com.psd.k4.security;

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;

import com.psd.k4.login.LoginServiceImpl;
import com.psd.k4.login.LoginVO;

@Service
public class SecurityUserDetailsService  implements  UserDetailsService {

	SecurityUserDetailsService(){
		System.out.println("===> SecurityUserDetailsService 실행");
	}
	
	@Autowired
	private LoginServiceImpl service; 
	
	@Override
	public UserDetails loadUserByUsername(String username) 
			throws UsernameNotFoundException {
		
		LoginVO vo = new LoginVO();
		
		System.out.println("===> vo 확인: " + vo );
		vo.setUsername(username);
		
		LoginVO  user = service.loginOK(vo);
		System.out.println("user 확인: " + user );
		
		// 아이디가 존재하는 지를 확인하여 존재하면 
		// new SecurityUser(user) 객체 생성하여 값을 넘긴다.
		if ( user == null) {
			throw  new  UsernameNotFoundException (username +" 사용자 없음");
		} else {
			System.out.println("===> new SecurityUser(user) 로 넘어간다.!! ");
			return new SecurityUser(user);
		}
		
	}

}

로그인 유저의 정보를 조회하기위해 jsp파일에서 맵핑된 곳으로 이동할때 <form> 태그의 Action를 사용하면 해당 클래스(스프링부트에서 자동으로 맵핑되는 경로)로 이동되지 않기 때문에 <form> 태그의 Action 제외한 jsp 파일을 생성하여 정확한 경로로 맵핑될 수 있도록 한다.

컨트롤러가 아닌 해당 클래스에서 아이디 존재 여부를 확인하기 때문이다.

  • 컨트롤러

로그인 컨트롤러

package com.psd.k4.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.psd.k4.login.LoginServiceImpl;

@Controller
public class LoginController {
	
	@Autowired
	LoginServiceImpl service;
	
	@RequestMapping("/index.do")
	String index() {		
		return "index.html";		
	}
	
	@RequestMapping("/login.do")
	String loginForm() {		
		return "loginForm.html";
		
	}
	
	@RequestMapping("/loginSuccess.do")
	String loginSuccess() {
		
		return "loginSuccess.html";
		
	}
				
	@RequestMapping("/accessDenied.do")
	String accessDenied() {
		
		return "accessDenied.html";
		
	}

}

로그인 동작 경로를 지정해주는 컨트롤러이다.


권한 컨트롤러

package com.psd.k4.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

import com.psd.k4.login.LoginServiceImpl;

@Controller
public class SecurityController {
	
	@Autowired
	LoginServiceImpl service;
	
	@RequestMapping("/member/member.do")
	String member() {		
		return "Success.html";
		
	}
	
	@RequestMapping("/manager/managerList.do")
	String manager() {
		
		return "Success.html";
		
	}
				
	@RequestMapping("/admin/adminList.do")
	String admin() {
		
		return "Success.html";
		
	}
	
	@RequestMapping("/everyone/adminList.do")
	String every() {
		
		return "Success.html";
		
	}
}

각 권한별 이동되는 페이지를 지정하는 컨트롤러이다.
해당 경로에 따라 이동되는 경로가 달라진다.

profile
Back-end Developer Preparation Students

1개의 댓글

comment-user-thumbnail
2023년 8월 1일

좋은 정보 감사합니다

답글 달기