관리 메뉴

DeseoDeSeo

[Spring Boot] Spring Boot Security 본문

spring/Spring Boot

[Spring Boot] Spring Boot Security

deseodeseo 2023. 10. 20. 18:45
SpringMVC10 복사 붙여넣기 해서 SpringMVC11로 이름 바꿈
pom.xml

 -> pom.xml 체크

		<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>

finish 누르면 이렇게 2개 추가됨.

그리고 아래 작성해서 추가해줌.

		<dependency>
			<groupId>org.springframework.security</groupId>
			<artifactId>spring-security-taglibs</artifactId>
		</dependency>
list.jsp

https://www.w3schools.com/bootstrap4/bootstrap_cards.asp

 

Bootstrap 4 Cards

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

 

BS4 Cards > Header and Footer 부분 가져오기

 

https://www.w3schools.com/bootstrap4/bootstrap_jumbotron.asp

 

Bootstrap 4 Jumbotron

W3Schools offers free online tutorials, references and exercises in all the major languages of the web. Covering popular subjects like HTML, CSS, JavaScript, Python, SQL, Java, and many, many more.

www.w3schools.com

Jumbotron > Full-width Jumbotron 부분 가져오기

 

kr.spring,entity > class생성 'Member'
package kr.spring.entity;

import javax.persistence.Entity;
import javax.persistence.EnumType;
import javax.persistence.Enumerated;
import javax.persistence.Id;

import lombok.Data;
import lombok.ToString;

@Entity
@Data
@ToString
public class Member {
	
	@Id
	private String username; //spring Security에서는 id가 아닌 username로 지정함.
	
	private String password; //spring Security에서는 pw가 아닌 password로 지정함.
	
	@Enumerated(EnumType.STRING) //@Enumerated -> 열거형(권한이 여러개임)
	private Role role; // 권한
	// ----------------여기까지는 반드시 필수로 넣어줘야한다.
	
	private String name; //이름
	private boolean ebled; // 계정활성화, 비활성화 부분
	
	
	
	
	
}
kr.spring.emtity > enum생성 'Role'
package kr.spring.entity;

public enum Role {
	ADMIN, MANAGER, MEMBER;
}
kr,spring.entity > class생성  ''CustomUser" 
package kr.spring.entity;

import java.util.Collection;

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

public class CustomUser extends User{
	
	private Member member;
	

	public CustomUser(Member member) {
		super(member.getUsername(), member.getPassword(), AuthorityUtils.createAuthorityList("ROLE_"+member.getRole().toString()));
		
		this.member = member;
		
	}
	// 우리가 만든 회원정보 -> Member
	//Spring Context holder에 저장하기 위해서는
	//User형태로 변환하여서 넣어줘야한다.
	//그걸 해주는 클래스가 바로 CustomUser 클래스임.
	
	
	
	
	
	
}
kr.spring > 패키지 생성  'kr.spring.config'

 

kr,spring.repository > interface 생성  'MemberRepository'
package kr.spring.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Service;

import kr.spring.entity.Member;


public interface MemberRepository extends JpaRepository<Member, String>{
	
	
}
kr.spring.config > class생성  ' SecurityConfiguration '
package kr.spring.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.web.builders.HttpSecurity;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;

@Configuration //환경설정 파일 설정
public class SecurityConfiguration {
	
	@Autowired
	private UserDetailsServiceImpl userService;
	
	@Bean
	public PasswordEncoder passwordEncoder() { //비밀번호 인코딩 기능
		
		
		return PasswordEncoderFactories.createDelegatingPasswordEncoder();
	}
	@Bean
	public SecurityFilterChain filterChain(HttpSecurity http) throws Exception{
		
		http.csrf().disable(); //csrf토큰 비활성화
		http.authorizeHttpRequests() //사용자의 요청을 핸들링
			.antMatchers("/","/member/**").permitAll() //  "/", "member"하위에 모든 접근을 허용하겠다.
			.antMatchers("/board/**").authenticated()  // board로 접근하는 모든 경우는 인증된(로그인한) 사용자만 허용됨.
			.and()  //추가
			.formLogin() //우리가 만든 별도의 로그인 폼을 사용하겠다.
			.loginPage("/member/login")//로그인 페이지는 member안에 login에서 하겠다.
			.defaultSuccessUrl("/board/list") //로그인 성공시 board list로 이동하겠다.
			.and() // 추가
			.logout()
			.logoutUrl("/member/logout") // 로그아웃 실행하고 싶다면 member/logout으로 요청하겠다.
			.logoutSuccessUrl("/"); //로그아웃하고 /로 이동하겠다.
			
		
		
		http.userDetailsService(userService);
		
		return http.build();
	}
	
}
src > webapp > web-inf > jsp생성 ' index.jsp '
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    
<%@ taglib prefix ="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix ="fn" uri="http://java.sun.com/jsp/jstl/functions" %>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt" %>

<c:set var="cpath" value="${pageContext.request.contextPath}" />
	    
    
    
<!DOCTYPE html>
<html lang="en">
<head>
  <title>Bootstrap Example</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/css/bootstrap.min.css">
  <script src="https://cdn.jsdelivr.net/npm/jquery@3.6.4/dist/jquery.slim.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js"></script>
  <script src="https://cdn.jsdelivr.net/npm/bootstrap@4.6.2/dist/js/bootstrap.bundle.min.js"></script>
</head>
<body>

 <div class="card" style=" width:600px; text-align:center; margin:0px auto;">
 
 	<div class="jumbotron jumbotron-fluid">
 		<div class="container">
 			<h1>Spring Boot</h1>
 			<p>Main page</p>
 		</div>
	 </div>
 
    <div class="card-body">
    	<p class="card-text" style="text-align:left;">메뉴를 선택하세요.</p>
      <div class="card-group">
      	<div class="card bg-warning">
      		<div class="card-body text-center">
      			<p class="card-text">글 목록 보기</p>
      		</div>
      	</div>
      	
      	<div class="card bg-danger">
      		<div class="card-body text-center">
      			<p class="card-text">로그인</p>
      		</div>
      	</div>
      	
      	
      	
      </div>
    </div>
  </div>


</body>
</html>

 

kr.spring.controller > class생성 ' HomeController.java'
package kr.spring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
public class HomeController {
	
	@RequestMapping("/")
	public String index() {
		return"index";
	}
}

이제 실행할 때 ,localhost:8081/boot해야됨.

 

web-inf > folder 생성 'member' > jsp 생성 ' login '

 

kr.spring.controller > controller생성 ' Membercontroller.java '
package kr.spring.controller;

import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;

@Controller
@RequestMapping("/member/*")
public class MemberController {
	
	
	@GetMapping("/login")
	public String login() {
		
		return "member/login";
	}
}

 

BoardServiceImpl.java
//상세보기
	@Override
	public Board get(Long idx) {
		Optional<Board> vo = boardRepository.findById(idx);  //board형태가 아니라 optional형태임.
		return vo.get(); //이렇게 하면 optional안에 있는걸 꺼내주는거임.
	}
optional : 원하는 값이 있으면 원하는 객체로 받고 없으면 Exceptional 처리를 하는 패턴임.
( NPE, NullPointerException)

 

list.jsp
	$(document).ready(function(){
			
			var regForm=$("#regForm");
			
			$("button").on("click",function(){//버튼의 모든 클릭을 감지하겠다.
				var oper = $(this).data("oper");
				if(oper=="register"){
					regForm.submit();
				}else if(oper=="reset"){
					regForm[0].reset();
				}else if(oper=="list"){
					location.href="${cpath}/list";	
				} else if(oper=="remove"){
					var idx = regForm.find("#idx").val();
					location.href="${cpath}/remove?idx="+idx;
				} else if(oper=="updateForm"){
					regForm.find("#title").attr("readonly",false);
					regForm.find("#content").attr("readonly",false);
					
					var upBtn="<button onclick='goUpdate()' class='btn btn-sm btn-info' type='button'>수정완료</button>";
					$("#update").html(upBtn);
					
				}
			});
location.href = " 이동할 페이지 주소 "

 

게시글 삭제하기
list.jsp

 

<input type="hidden" id="idx" name="idx" value="">

idx값을 hidden으로 숨기고

function printBoard(vo){
			var regForm = $("#regForm");
			regForm.find("#title").val(vo.title);//title을 찾아서 value을 넣을 것이다
			regForm.find("#content").val(vo.content);//title을 찾아서 value을 넣을 것이다
			regForm.find("#writer").val(vo.writer);//title을 찾아서 value을 넣을 것이다
			
			regForm.find("input").attr("readonly", true);
			regForm.find("textarea").attr("readonly", true);
			//상세보기를 누르면 목록,수정,삭제가 나옴.
			$("#regDiv").css("display", "none");
			$("#updateDiv").css("display", "block");
			
			regForm.find("#idx").val(vo.idx);
		}
regForm.find("#idx").val(vo.idx);
: 게시글 불러올 때, input의 idx를 찾아서 idx값을 넣어준다.
 else if(oper=="remove"){
		var idx = regForm.find("#idx").val();
		location.href="${cpath}/remove?idx="+idx;
}
이렇게 하면 클릭할 때마다 url뒤에 idx값이 넘어간다.

 

BoardService.java
	public void delete(Long idx);

 

BoardServiceImpl.java
	@Override
	public void delete(Long idx) {
		boardRepository.deleteById(idx);
	}

 

게시판 수정하기
list. jsp
<div id="updateDiv" style="display: none;">
 		<button class="btn btn-sm btn-primary" data-oper="list" type="button">목록</button>
	<span id="update">
		<button class="btn btn-sm btn-warning" data-oper="updateForm" type="button">수정</button>
	</span>
		<button class="btn btn-sm btn-success" data-oper="remove" type="button">삭제</button>
</div>
수정 하고 나서 수정완료 버튼으로 바꿔주기 위해서 span태그로 감싼다.
else if(oper=="updateForm"){
		regForm.find("#title").attr("readonly",false);
    	regForm.find("#content").attr("readonly",false);
		var upBtn="<button onclick='goUpdate()' class='btn btn-sm btn-info' type='button'>수정완료</button>";
		$("#update").html(upBtn);
					
}
readonly속성 풀어주고 새로운 버튼을 추가한다. 
버튼을 누르면 update가 작동한다.
function goUpdate(){
			var regForm =$("#regForm");
			regForm.attr("action","${cpath}/modify");
			regForm.submit();
		}

 

BoardService.java
public void update(Board vo);
BoardServiceImpl.java
@Override
	public void update(Board vo) {
		//JPA의 SAVE메서드는 새로운pk값 또는 없는 값이 들어오면 insert기능을
		// 기존에 존재하는 pk값이 들어오면 update기능을 함.
		boardRepository.save(vo);	
	}

'spring > Spring Boot' 카테고리의 다른 글

[Spring Boot ] 로그인 구현  (0) 2023.10.23
ミ★ Spring boot 02  (1) 2023.10.20
ミ★ Spring Boot 01  (0) 2023.10.16