본문 바로가기
👨‍💻 2. 웹개발_Back end/2-7 Spring Boot

[SpringBoot] 3장 스프링부트 시큐리티(spring boot security)

by 달님🌙 2021. 11. 8.
반응형

 

실습 코드 참조

 

moonhy7/SpringBoot: SpringBoot 실습 코드 정리 (github.com)

 

GitHub - moonhy7/SpringBoot: SpringBoot 실습 코드 정리

SpringBoot 실습 코드 정리. Contribute to moonhy7/SpringBoot development by creating an account on GitHub.

github.com

 

 

1. 테이블 생성 및 데이터 추가

 

1. 쿼리 작성

CREATE TABLE MEMBER (
	ID VARCHAR(10) PRIMARY KEY,
    PASSWORD VARCHAR(100),
    NAME VARCHAR(30),
    ROLE VARCHAR(12),
    ENABLED VARCHAR(1)
);

SELECT * FROM MEMBER;

INSERT INTO MEMBER (ID, PASSWORD, NAME, ROLE, ENABLED) VALUES ('member', 'member123', '회원', 'ROLE_MEMBER', 'Y');
INSERT INTO MEMBER (ID, PASSWORD, NAME, ROLE, ENABLED) VALUES ('manager', 'manager123', '매니저', 'ROLE_MANAGER', 'Y');
INSERT INTO MEMBER (ID, PASSWORD, NAME, ROLE, ENABLED) VALUES ('admin', 'admin123', '어드민', 'ROLE_ADMIN', 'Y');

 

2. 테이블 생성

 

 

2. 스프링부트 기본 씨큐리티

1. build.gradle

implementation 'org.springframework.boot:spring-boot-starter-security:2.5.6'
testImplementation 'org.springframework.security:spring-security-test:5.5.3'

 

2. 콘솔창에 비밀번호가 나옴

3. 결과 화면

 

4. 로그인 성공

 

 

3. DB에 저장한 Member 정보로 로그인

 

1. SecurityConfiguration 클래스 생성

package com.springbook.configuration;

import org.springframework.beans.factory.annotation.Autowired;
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;

@EnableWebSecurity
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
	@Autowired
	private UserDetailsServiceImpl userDetailsServiceImpl;
	
	@Override
	protected void configure(HttpSecurity security) throws Exception {
		//authorizeRequests() : 사용자 인증과 권한 설정
		//antMathers() : 매칭되는 url 패턴에 대한 접근 설정
		//permitAll() : 모든 사용자 접근 허용
		//hasRole() : 특정 권한의 사용자만 접근 허용
		//authenticated() : 인증된 사용자에게만 접근 허용
		security.authorizeRequests().antMatchers("/").permitAll()
									.antMatchers("/member/**").authenticated()
									.antMatchers("/manager/**").hasRole("ROLE_MANAGER")
									.antMatchers("/admin/**").hasAnyRole("ROLE_ADMIN");
		
		//로그인 처리
		security.formLogin().loginPage("/login.do").defaultSuccessUrl("/loginSuccess.do", true);
		//로그아웃 처리
		security.logout().invalidateHttpSession(true).logoutSuccessUrl("/login.do");
		
		security.userDetailsService(userDetailsServiceImpl);
		
	}
}

 

2. MemberController

package com.springbook.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;

@Controller
public class MemberController {

	@Autowired
	private PasswordEncoder encoder;
	
	@GetMapping("/login.do")
	public String loginView() {
		return "login";
	}
	
	@PostMapping("/loginSuccess.do")
	public String loginSuccess() {
		return "loginSuccess";
	}
	
	@GetMapping("logout.do")
	public String logout() {
		return "login";
	}
}

 

3. UserDetailsServiceImpl

package com.springbook.impl;

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.springbook.mapper.UserMapper;
import com.springbook.vo.MemberVO;
import com.springbook.vo.SecurityUser;

@Service
public class UserDetailsServiceImpl implements UserDetailsService {
	@Autowired
	private UserMapper userMapper;
	
	@Override
	public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
		MemberVO member = userMapper.findById(username);
		
		if(member == null) {
			throw new UsernameNotFoundException(username + " 사용자 없음");
		} else {
			return new SecurityUser(member);
		}
	}
}

 

4. MemberVO

package com.springbook.vo;

import lombok.Data;

@Data
public class MemberVO {
	private String id;
	private String password;
	private String name;
	private String role;
	private String enalbed;
}

 

5. SecurityUser

package com.springbook.vo;

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

public class SecurityUser extends User {
	private static final long serialVersionUID = 1L;

	public SecurityUser(MemberVO member) {
		super(member.getId(), member.getPassword(), 
				AuthorityUtils.createAuthorityList(member.getRole().toString()));
	}
}

 

6. user-mapping.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!-- mapper DTD 선언 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.springbook.mapper.UserMapper">
	<select id="findById" parameterType="int" resultType="com.springbook.vo.BoardFileVO">
		SELECT * FROM BOARD_FILE
			WHERE SEQ = #{seq}
	</select>
	
</mapper>

 

7. UserMapper

package com.springbook.mapper;

import org.apache.ibatis.annotations.Mapper;

import com.springbook.vo.MemberVO;

@Mapper
public interface UserMapper {
	MemberVO findById(String username);
}

 

8. 실행 화면

 

 

 

 

 

* 403 에러 해결

- 아래 코드를 SecurityConfiguration.java 파일에 추가하면 된다.

//크로스 도메인 사이트 위조 요청에 대한 설정
//비활성화해서 어디서든 접근 가능하도록 설정
security.csrf().disable();

 

 

4. 패스워드 암호화하여 DB 저장

 

1. UserMapper 클래스 생성

package com.springbook.mapper;

import org.apache.ibatis.annotations.Mapper;

import com.springbook.vo.MemberVO;

@Mapper
public interface UserMapper {
	MemberVO findById(String username);
	
	void join(MemberVO vo);
}

 

2. MemberService

package com.springbook.service;

import com.springbook.vo.MemberVO;

public interface MemberService {
	void join(MemberVO vo);
}

 

3. MemberServiceImpl

package com.springbook.impl;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.springbook.mapper.UserMapper;
import com.springbook.service.MemberService;
import com.springbook.vo.MemberVO;

@Service
public class MemberServiceImpl implements MemberService {
	@Autowired
	private UserMapper userMapper;
	
	@Override
	public void join(MemberVO vo) {
		userMapper.join(vo);
	}
}

 

4. user-mapping.xml

<?xml version="1.0" encoding="UTF-8" ?>
<!-- mapper DTD 선언 -->
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">

<mapper namespace="com.springbook.mapper.UserMapper">
	<select id="findById" parameterType="int" resultType="com.springbook.vo.BoardFileVO">
		SELECT * FROM BOARD_FILE
			WHERE SEQ = #{seq}
	</select>
	
	<insert id="join" parameterType="com.springbook.vo.MemberVO">
		INSERT INTO MEMBER (
								ID
								, PASSWORD
								, NAME
								, ROLE
								, ENABLED
							)
					VALUES (
								 #{id}
							   , #{password}
							   , #{name}
							   , 'ROLE_MEMBER'
							   , 'Y'	
							)
	</insert>
	
</mapper>

 

5. 실행 화면

 

- 비밀번호가 PASSWORD 컬럼에 암호화되어 저장된다.

 

 

반응형

댓글