Back-End/Java

[Spring] 스프링 Security 게시판 및 파일첨부 예제

CJun 2021. 6. 24. 23:27
반응형

 

 

[Spring] 스프링 Security 로그인 예제

[Spring] 스프링 Security 사용이유와 설정 방법을 알아보자 spring security 란 ? Spring 기반의 애플리케이션의 은증과 권한, 인가 등의 보안을 담당하는 스프링 하위 프레임 워크이다. 처리 방법으로는 Fi

soulno.tistory.com

 

src/main/java/com/mycom.myapp/
BoardController.java
파일경로 및 insert 하기
package com.mycom.myapp;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.util.FileCopyUtils;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.multipart.MultipartFile;

import com.mysecurity.dto.Board;
import com.mysecurity.service.BoardService;

@Controller
@RequestMapping("board/*")
public class BoardController {
	@Autowired
	private BoardService bservice;
	
	@GetMapping("insert")
	@PreAuthorize("isAuthenticated()")
	public void insert() {}
		
	@PostMapping("insert")
	public String insert(Board board, HttpServletRequest request) throws IOException {
		String saveDir = request.getSession().getServletContext().getRealPath("/");
		saveDir+="resources\\img\\";
		System.out.println("saveDir" + saveDir);
		
		MultipartFile f = board.getUploadFile();
		String fileName="";
		
		if(!f.isEmpty()) { // 파일이 있다면
			String orifileName=f.getOriginalFilename();
			// System.out.println("orifileName : " + orifileName);
			// 파일명 지정
			UUID uuid = UUID.randomUUID();
			fileName = uuid+"_"+orifileName;
			//FileCopyUtils.copy(f.getBytes(), new File(saveDir+fileName));
			f.transferTo(new File(saveDir+fileName));
			board.setBimg(fileName);
		}
		bservice.insert(board);
		return "redirect:list";
	
	}
	
	@GetMapping("list")
	public String list(Model model) {
		List<Board> lists = bservice.list();
		model.addAttribute("lists", lists);
		return "board/list";
	}
	
	
}

 

src/main/java/com/dto/
Board.java
package com.mysecurity.dto;

import org.springframework.web.multipart.MultipartFile;

import lombok.Data;

@Data
public class Board {
	private int num;
	private String title;
	private String writer;
	private String content;
	private MultipartFile uploadFile;
	private String bimg; //파일이 저장되는 파일명
}

 

src/main/java/com/mapper/
BoardMapper.java
package com.mysecurity.mapper;

import java.util.List;

import com.mysecurity.dto.Board;

public interface BoardMapper {
	public void insert(Board board);
	public List<Board> list();
	
}

 

src/main/java/com/respository/
BoardRespository.java
package com.mysecurity.repository;

import java.util.List;

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

import com.mysecurity.dto.Board;
import com.mysecurity.mapper.BoardMapper;

@Repository
public class BoardRespository {
	@Autowired
	private BoardMapper boardMapper;
	public void insert(Board board) {
		boardMapper.insert(board);
	}
	public List<Board> list() {
		return boardMapper.list();
	}
}

 

src/main/java/com/service/
BoardService.java
package com.mysecurity.service;

import java.util.List;

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

import com.mysecurity.dto.Board;
import com.mysecurity.mapper.BoardMapper;
import com.mysecurity.repository.BoardRespository;

import lombok.Setter;

@Service
public class BoardService {

	@Autowired
	private BoardRespository boardRepository;
	
	public void insert(Board board) {
		boardRepository.insert(board);
	}
	
	public List<Board> list() {
		return boardRepository.list();
	}
	
}

 

src/main/resources/com/mysecurity/mapper/
BoardMapper.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
  PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
  "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<!--   mapper 가 어떤 파일과 같이 연동되서 쓰일지 보여준다 -->
<mapper namespace="com.mysecurity.mapper.BoardMapper">

<insert id="insert">
insert into tbl_board(title, writer, content, bimg)
VALUES (#{title}, #{writer}, #{content}, #{bimg})
</insert>

<select id="list" resultType="com.mysecurity.dto.Board">
select * from tbl_board
</select>


</mapper>

 

insert.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
    <!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://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</head>
<body>
<h1>Board insert</h1>
<br />
<form action="insert" method="post" enctype="multipart/form-data">
  <div class="form-group">
    <label for="title">제목:</label>
    <input type="text" class="form-control" id="title" name="title">
 
  </div>
  <div class="form-group">
    <label for="writer">글쓴이:</label>
     <input type="text" class="form-control" id="writer" name="writer">

  </div>
  <div class="form-group">
    <label for="content">내용:</label>
    <textarea id="content" name="content" id="content" class="form-control" ></textarea>
  </div>
  
  <div class="form-group">
    <label for="file">파일:</label>
    <input type="file" class="form-control" id="uploadFile" name="uploadFile">
    
  </div>
  
  <button type="submit" class="btn btn-primary">글쓰기</button>
</form>
</body>
</html>

 

list.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
    pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>List</title>
<meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</head>
<body>
<c:forEach items="${lists }" var="board">
<div class="container">
  <h2>Card Image</h2>
  <p>Image at the top (card-img-top):</p>
  <div class="card" style="width:400px">
    <img class="card-img-top" src="img_avatar1.png" alt="Card image" style="width:100%">
    <div class="card-body">
      <h4 class="card-title">제목 : ${board.title }</h4>
      <p class="card-text">Some example text some example text. John Doe is an architect and engineer</p>
      <a href="#" class="btn btn-primary">See Profile</a>
    </div>
  </div>
  <br>
  
  <h2>Card Image</h2>
  <p>Image at the top (card-img-top):</p>
  <div class="card" style="width:400px">
    <img class="card-img-top" src="img_avatar1.png" alt="Card image" style="width:100%">
    <div class="card-body">
      <h4 class="card-title">작성자 : ${board.writer } <br></h4>
      <p class="card-text">Some example text some example text. John Doe is an architect and engineer</p>
      <a href="#" class="btn btn-primary">See Profile</a>
    </div>
  </div>
  <br>
  
  <h2>Card Image</h2>
  <p>Image at the top (card-img-top):</p>
  <div class="card" style="width:400px">
    <img class="card-img-top" src="img_avatar1.png" alt="Card image" style="width:100%">
    <div class="card-body">
      <h4 class="card-title">내용 : ${board.content } <br></h4>
      <p class="card-text">Some example text some example text. John Doe is an architect and engineer</p>
      <a href="#" class="btn btn-primary">See Profile</a>
    </div>
  </div>
  <br>
  
  <p>Image at the bottom (card-img-bottom):</p>
  <div class="card" style="width:400px">
    <div class="card-body">
      <h4 class="card-title">파일 : ${board.bimg }</h4>
      <p class="card-text">Some example text some example text. Jane Doe is an architect and engineer</p>
      <a href="#" class="btn btn-primary">See Profile</a>
    </div>
    <img class="card-img-bottom" src="/myapp/resources/img/${board.bimg }" alt="Card image" style="width:100%">
  </div>
</div>


<%-- 제목 : ${board.title } <br>
작성자 : ${board.writer } <br>
내용 : ${board.content } <br>
파일 : ${board.bimg } <br>
<img src="/myapp/resources/img/${board.bimg }" width="100" height ="100"> --%>

</c:forEach>
</body>
</html>

 

src/main/webapp/WEB-INF-spring/
root-context.xml
DB연결과 Spring Bean 설정
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:mybatis-spring="http://mybatis.org/schema/mybatis-spring"
	xmlns:context="http://www.springframework.org/schema/context"
	xsi:schemaLocation="http://mybatis.org/schema/mybatis-spring http://mybatis.org/schema/mybatis-spring-1.2.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-4.3.xsd">

	<!-- Root Context: defines shared resources visible to all other web components -->
	<bean id="hikariConfig" class="com.zaxxer.hikari.HikariConfig">
		<property name="driverClassName"
			value="com.mysql.cj.jdbc.Driver" />
		<property name="jdbcUrl"
			value="jdbc:mysql://localhost:3306/springdb?useSSL=false&amp;serverTimezone=Asia/Seoul&amp;characterEncoding=UTF-8" />
		<property name="username" value="root" />
		<property name="password" value="1234" />
	</bean>
	<!-- DB연결 객체 -->
	<bean id="ds" class="com.zaxxer.hikari.HikariDataSource"
		destroy-method="close">
		<constructor-arg ref="hikariConfig" />
	</bean>

	<!--Mybatis sqlSessionFactoryBean -->
	<bean id="sqlSessionFactoryBean"
		class="org.mybatis.spring.SqlSessionFactoryBean">
		<property name="dataSource" ref="ds" />
	</bean>
	<mybatis-spring:scan base-package="com.mysecurity.mapper"/>
	<context:component-scan base-package="com.mysecurity.repository, com.mysecurity.service"/>
</beans>

 

src/main/webapp/WEB-INF-spring/
security-context.xml
글쓰기 할때 로그인을 완료한사람만 권한주기

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:security="http://www.springframework.org/schema/security"
	xsi:schemaLocation="http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
		http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">

<bean id="bcryptPasswordEncoder"
class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
<bean id="customUserDetailsService" class="com.mysecurity.domain.CustomUserDetailsService"/>
<bean id ="customLoginSuccess" class="com.mysecurity.domain.CustomLoginSuccess" />
<security:http>
	<security:intercept-url pattern="/all" access="permitAll"/>
	<security:intercept-url pattern="manager" access="hasRole('ROLE_MANAGER')"/>
	
	<security:form-login login-page="/customLogin"
	authentication-success-handler-ref="customLoginSuccess"/>
	<security:csrf disabled="true"/>
	<security:logout logout-url="/customLogout" invalidate-session="true"/>
</security:http>


<security:authentication-manager>
	<security:authentication-provider user-service-ref="customUserDetailsService">
		<security:password-encoder ref="bcryptPasswordEncoder"/>
	</security:authentication-provider>
</security:authentication-manager>


</beans>

 

src/main/webapp/WEB-INF-spring/appservlet
servlet-context.xml

파일업로드 구현할때 가장 중요한 파일사이즈, multipartResolver

 

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/mvc"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:beans="http://www.springframework.org/schema/beans"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:security="http://www.springframework.org/schema/security"
	xsi:schemaLocation="http://www.springframework.org/schema/security https://www.springframework.org/schema/security/spring-security.xsd
		http://www.springframework.org/schema/mvc https://www.springframework.org/schema/mvc/spring-mvc.xsd
		http://www.springframework.org/schema/beans https://www.springframework.org/schema/beans/spring-beans.xsd
		http://www.springframework.org/schema/context https://www.springframework.org/schema/context/spring-context.xsd">

	<!-- DispatcherServlet Context: defines this servlet's request-processing infrastructure -->
	
	<!-- Enables the Spring MVC @Controller programming model -->
	<annotation-driven />

	<!-- Handles HTTP GET requests for /resources/** by efficiently serving up static resources in the ${webappRoot}/resources directory -->
	<resources mapping="/resources/**" location="/resources/" />

	<!-- Resolves views selected for rendering by @Controllers to .jsp resources in the /WEB-INF/views directory -->
	<beans:bean class="org.springframework.web.servlet.view.InternalResourceViewResolver">
		<beans:property name="prefix" value="/WEB-INF/views/" />
		<beans:property name="suffix" value=".jsp" />
	</beans:bean>
	
	<!-- file upload -->
	<beans:bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
	<beans:property name="maxUploadSize" value="10485760" /> <!-- 10MB -->
	
	</beans:bean>
	
	
	<security:global-method-security pre-post-annotations="enabled" />
	
	<context:component-scan base-package="com.mycom.myapp" />
	
	
	
</beans:beans>

반응형