Spring(2023-04-17)

권단비·2023년 4월 17일
0

IT

목록 보기
123/139

[github]

[restful]

json viewer

https://chrome.google.com/webstore/detail/json-viewer/gbmdgpbipfallnflgajpaliibnhdgobh?hl=ko

static : 정적 리소스(html, css, js, image..)
정적 리소스 : 컴파일 대상이 아닌 것
동적 리소스 : jsp
[Get | Post 방식]
게시판 수정 1번 url : /update?bid=1
게시판 삭제 20번 url : /delete?bid=20
  
[restful 처리]
게시판 삭제 20번 수정 또는 삭제 url : /boards/20
>> method 방식에 따라 [/boards/20] 수정되거나 삭제됨
>> html에서는 method 방식을 get, post만 지원함


[계산 application.properties]
#server port number
server.port = 8282

#datasource (oracle)
#spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
#spring.datasource.url=jdbc:oracle:thin:@localhost:1521/xe
spring.datasource.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
spring.datasource.url=jdbc:log4jdbc:oracle:thin:@localhost:1521/xe
spring.datasource.username=scott
spring.datasource.password=tiger

#MyBatis
#xml location
mybatis.mapper-locations=classpath:mappers/`**/*.xml
mybatis.type-aliases-package=edu.global.ex

#jsp 
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
---------------------------------------------------------------------
[계산 RestBoardController.java]
package edu.global.ex.controller;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import edu.global.ex.BoardService;
import edu.global.ex.vo.BoardVO;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

@Slf4j // 로그를 사용하기 위한 어노테이션 : log.info("view_list()..");
@RequestMapping("/rboard/*") // jboard로 들어오는 모든 것들은 BoardController를 생성해라
@RequiredArgsConstructor
@RestController // 기존의 컨트롤러 문법과는 완전히 달라짐 | restful 처리를 위한 어노테이션
public class RestBoardController {

	@Autowired // (주입)객체에 주소를 줌
	private BoardService boardService; // BoardService boardService = new BoardServiceImpl();

	@GetMapping("/")
	public String rboard() { // String이면 html text로 보냄
		return "<h1>이제는 restful이다</h1>";
	}

	@GetMapping("/list") // List객체 json으로 리턴
	public List<BoardVO> list() {
		log.info("list()..");
		return boardService.getList();
	}
	// json으로 리턴된 데이터는 ajax로 받아온다.
	// ajax({ type:"GET", url : "http://localhost:8282/rboard/list",
	// success : function(result){}

	@DeleteMapping("/{bid}") // /rboard/1054
	public int rest_delete(BoardVO boardVO) {
		log.info("rest_delete()..");
		return boardService.remove(boardVO);
	}

	/*
	 * @DeleteMapping("/{bid}") public ResponseEntity<String> rest_delete(BoardVO
	 * boardVO, Model model) {
	 * 
	 * ResponseEntity<String> entity = null; log.info("rest_delete..");
	 * 
	 * try { int rn = boardService.remove(boardVO); // 삭제가 성공하면 성공 상태메시지 저장
	 * log.info("delete 넘어온 숫자:::::" + rn);
	 * 
	 * entity = new ResponseEntity<>(String.valueOf(rn), HttpStatus.OK); } catch
	 * (Exception e) { e.printStackTrace(); // 댓글 삭제가 실패하면 실패 상태메시지 저장 entity = new
	 * ResponseEntity<String>(e.getMessage(), HttpStatus.BAD_REQUEST); } // 삭제 처리
	 * HTTP 상태 메시지 리턴 return entity; }
	 */

	@GetMapping("/{bid}")
	public BoardVO rest_content_view(BoardVO boardVO) {
		log.info("rest_content_view()..");
		return boardService.get(boardVO.getBid());
	}

	// @RequestBody : json을 자바 객체로 변환하는 어노테이션
	@PutMapping("/{bid}")
	public int rest_update(@RequestBody BoardVO boardVO) {
		log.info("rest_update()..");
		return boardService.modify(boardVO);
	}
}
---------------------------------------------------------------------
[계산 rest_lsit.html]
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script
	src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script type="text/javascript">
	$(document).ready(function() {
		$.ajax({
			type : "GET",
			url : "/rboard/list/",
			success : function(result) {
				console.log(result);
				var htmls = "";
				$("#list-table").html(""); // table을 갖고옴, html을 초기화

				$("<tr>" , {
		            html : "<td>" + "번호" + "</td>"+  // 컬럼명들
		                  "<td>" + "이름" + "</td>"+
		                  "<td>" + "제목" + "</td>"+
		                  "<td>" + "날짜" + "</td>"+            
		                  "<td>" + "히트" + "</td>"
		         }).appendTo("#list-table") // 이것을 테이블에 붙임

		         if(result.length < 1){
		             htmls.push("등록된 댓글이 없습니다.");
		          } else {
		                     $(result).each(function(){                         >
		                        htmls += '<tr>';
		                        htmls += '<td>'+ this.bid + '</td>';
		                        htmls += '<td>'+ this.bname + '</td>';
		                        htmls += '<td>'
		                      for(var i=0; i < this.bindent; i++) { //for 문은 시작하는 숫자와 종료되는 숫자를 적고 증가되는 값을 적어요. i++ 은 1씩 증가 i+2 는 2씩 증가^^
		                         htmls += '-'   
		                     }
		                        htmls += '<a href="/rest_content_view.html?bid=' + this.bid + '">' + this.btitle + '</a></td>';
		                       htmls += '<td>'+ this.bdate + '</td>'; 
		                        htmls += '<td>'+ this.bhit + '</td>';
		                        htmls += '<td>'+ '<input id=' + this.bid + " type='button' class='btn_delete' value='삭제'>" + '</td>';
		                        htmls += '</tr>';                               
		                    });   //each end

		                    htmls+='<tr>';
		                    htmls+='<td colspan="5"> <a href="/write_view">글작성</a> </td>';                         
		                    htmls+='</tr>';
		          }

		          $("#list-table").append(htmls);
			},
			error : function(e) {
				console.log(e);
			}
		});
	});
</script>

<!-- <input id="142" type="button" class="btn_delete" value="삭제"> -->
<script type="text/javascript">
$(document).ready(function(){
	$(document).on("click","#list-table .btn_delete", function(){
		console.log($(this).attr("id"));

		 var id = $(this).attr("id");
                $(this).parent().parent().remove(); // tr태그를 지워라

         $.ajax({
             type : "DELETE",
             url : "/rboard/" + id,
             success: function (result) {       
                console.log("삭제된 수" + result);
             },
             error: function (e) {
                 console.log(e);
             }
         });
    });
});
</script>
</head>
<body>
	<table id="list-table" width="500" cellpadding="0" cellspacing="0"
		border="1" style="text-align: center">
	</table>
</body>
</html>
---------------------------------------------------------------------
[계산 rest_content_view.html]
<!DOCTYPE>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>Insert title here</title>
<script
	src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>

<!-- http://localhost:8282/rest_content_view.html?bid=254 -->
<script type="text/javascript">
	$(document).ready(function() {
		let searchParams = new URLSearchParams(window.location.search)
		console.log(searchParams.has('bid'));

		let bid = searchParams.get('bid')
		console.log(bid);

		$.ajax({
			type : "GET",
			url : "/rboard/" + bid,
			success : function(board) {

				console.log(board);
				$("#input_hidden").val(board.bid);
				$("#td_bid").text(board.bid);
				$("#td_hit").text(board.bhit);

				$("#input_bname").val(board.bname);
				$("#input_btitle").val(board.btitle);
				$("#textarea_bcontent").text(board.bcontent);
			},
			error : function(e) {
				console.log(e);
			}
		})
	});
</script>

<script type="text/javascript">
	$(document).ready(function() {
		$("#updateForm").submit(function(event) {
			//prevendDefault()는 href로 연결해 주지 않고 단순히 click에 대한 처리를 하도록 해준다.

			event.preventDefault();
			console.log("ajax 호출전");

			var bname = $("#input_bname").val();
			var btitle = $("#input_btitle").val();
			var bcontent = $("#textarea_bcontent").text();
			var bid = $("#input_hidden").val();

			var form = {
				bid : bid,
				bname : bname,
				btitle : btitle,
				bcontent : bcontent
			};
			$.ajax({
				type : "PUT",
				url : "/rboard/" + bid,
				cashe : false,
				contentType : 'application/json; charset=utf-8', // var form객체를 json으로 보내겠다
				data : JSON.stringify(form), // json으로 변경
				success : function(result) {
					console.log(result);
					$(location).attr('href', '/rest_list.html') // location.href = '/rest_list.html'
				},
				error : function(e) {
					console.log(e);
				}
			})
		});
	});
</script>
</head>
<body>

	<table id="list-table" width="500" cellpadding="0" cellspacing="0"
		border="1">
		<form id="updateForm" action="modify" method="post">
			<input id="input_hidden" type="hidden" name="bid" value="">
			<tr>
				<td>번호</td>
				<td id="td_bid"></td>
			</tr>
			<tr>
				<td>히트</td>
				<td id="td_hit"></td>
			</tr>
			<tr>
				<td>이름</td>
				<td><input id="input_bname" type="text" name="bname" value=""></td>
			</tr>
			<tr>
				<td>제목</td>
				<td><input id="input_btitle" type="text" name="btitle" value=""></td>
			</tr>
			<tr>
				<td>내용</td>
				<td><textarea id="textarea_bcontent" rows="10" name="bcontent"></textarea></td>
			</tr>
			<tr>
				<td colspan="2"><input id="input_modify" type="submit"
					value="수정"> &nbsp;&nbsp; <a href="rest_list.html">목록보기</a>
					&nbsp;&nbsp; <a id="a-delete"
					href="${pageContext.request.contextPath}/rest/delete?bid=${content_view.bid}">삭제</a>
					&nbsp;&nbsp; <a href="reply_view?bId=${content_view.bid}">답변</a></td>
			</tr>
		</form>
	</table>
</body>
</html>
[결과값]


[스프링 시큐리티]

스프링 시큐리티(인증과 권한) = 인증과 권한을 위한 솔루션(프레임워크)

1) 인증과 권한
2) 암호화 모듈 제공
3) CSRF 방어 모듈 제공
[스텝 1]
dependency만 추가해도 Spring Security에서 제공하는 가장 기본적인 인증이 바로 적용됨

기본 로그인 화면이 가장 먼저 나올 것이다.
Username : user (기본 계정)
Password : 비밀번호는 어플리케이션 기동할때 로그로 나오는 Using generated security password 정보
Using generated security password: 0d07e7fd-0fba-403d-9eff-149ac84f4d56

This generated password is for development use only. Your security configuration must be updated before running your application in production.
------------------------------------------------------------------------------------------------
[스텝 2]
   이미지(가영이)가 보이지 않는다.
   우선 정적파일들은 시큐리티에 적용되지 않도록 아래와 같이 설정을 한다.
    이제 더이상 리소스파일들은 스프링 시큐리티에서 관리를 하지 않는다.   

   @Override
   public void configure(WebSecurity web) throws Exception {
      // web.ignoring().requestMatchers(PathRequest.toStaticResources().atCommonLocations());
      web.ignoring().antMatchers("/css/**", "/js/**", "/img/**", "/lib/**");
   }
------------------------------------------------------------------------------------------------
[스텝 3]
이제 설정에서 유저를 생성한후 , 다시 한번 접속해 보자 , 로그인 창에서 아래의 이름과 비밀번호로 접속해 보자. 그럼 헬로우 월드가 보인다.
   
   @Override
   protected void configure(AuthenticationManagerBuilder auth) throws Exception {
       auth.inMemoryAuthentication()
               .withUser("member").password("{noop}member").roles("USER").and()
               .withUser("admin").password("{noop}admin").roles("ADMIN");
   }
------------------------------------------------------------------------------------------------
[스텝 4]
home.jsp를 제대로 만들고, 아래와 같이 설정하여 / 로 접속후 home.jsp 가 나오는것을 확인한다.

   @Override
   protected void configure(HttpSecurity http) throws Exception {
      //우선 CSRF설정을 해제한다.
      //초기 개발시만 해주는게 좋다.
      http.csrf().disable();
      
      http.authorizeRequests()
      .antMatchers("/member/**").hasAnyRole("ROLE_MEMBER") 
      .antMatchers("/admin/**").hasAnyRole("ROLE_ADMIN")
      .antMatchers("/**").permitAll();      
   }
------------------------------------------------------------------------------------------------
[스텝 5]
1.home.jsp를 제대로 만들고, 아래와 같이 설정하여 / 로 접속후 home.jsp 가 나오는것을 확인한다.
2 admin 페이지와 user 페이지를 만든후, 컨트롤러를 작성하여, admin 과 user 계정으로 접속후 각각의 지정된 페이지로 접속 되는지 확인한다.

   protected void configure(HttpSecurity http) throws Exception {
      //우선 CSRF설정을 해제한다.
      //초기 개발시만 해주는게 좋다.
      http.csrf().disable();
      
      http.authorizeRequests()
      .antMatchers("/user/**").hasAnyRole("USER") 
      .antMatchers("/admin/**").hasAnyRole("ADMIN")
      .antMatchers("/**").permitAll();
      
      http.formLogin(); //스프링 시큐리티에 있는 기본 로그인 폼을 사용하겠다.

git hub에 올리고 싶지 않은 파일 정리

https://www.toptal.com/developers/gitignore
C:\Users\USER\Documents\workspace-sts-3.9.11.RELEASE\spring_boot_kdb_security

HELP.md
target/
!.mvn/wrapper/maven-wrapper.jar
!**/src/main/**/target/
!**/src/test/**/target/

### STS ###
.apt_generated
.classpath
.factorypath
.project
.settings
.springBeans
.sts4-cache

### IntelliJ IDEA ###
.idea
*.iws
*.iml
*.ipr

### NetBeans ###
/nbproject/private/
/nbbuild/
/dist/
/nbdist/
/.nb-gradle/
build/
!**/src/main/**/build/
!**/src/test/**/build/

### VS Code ###
.vscode/

# Created by https://www.gitignore.io/api/java,macos,windows,eclipse
# Edit at https://www.gitignore.io/?templates=java,macos,windows,eclipse

### Eclipse ###
.metadata
bin/
tmp/
*.tmp
*.bak
*.swp
*~.nib
local.properties
.settings/
.loadpath
.recommenders

# External tool builders
.externalToolBuilders/

# Locally stored "Eclipse launch configurations"
*.launch

# PyDev specific (Python IDE for Eclipse)
*.pydevproject

# CDT-specific (C/C++ Development Tooling)
.cproject

# CDT- autotools
.autotools

# Java annotation processor (APT)
.factorypath

# PDT-specific (PHP Development Tools)
.buildpath

# sbteclipse plugin
.target

# Tern plugin
.tern-project

# TeXlipse plugin
.texlipse

# STS (Spring Tool Suite)
.springBeans

# Code Recommenders
.recommenders/

# Annotation Processing
.apt_generated/

# Scala IDE specific (Scala & Java development for Eclipse)
.cache-main
.scala_dependencies
.worksheet

### Eclipse Patch ###
# Eclipse Core
.project

# JDT-specific (Eclipse Java Development Tools)
.classpath

# Annotation Processing
.apt_generated

.sts4-cache/

### Java ###
# Compiled class file
*.class

# Log file
*.log

# BlueJ files
*.ctxt

# Mobile Tools for Java (J2ME)
.mtj.tmp/

# Package Files #
*.jar
*.war
*.nar
*.ear
*.zip
*.tar.gz
*.rar

# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml
hs_err_pid*

### macOS ###
# General
.DS_Store
.AppleDouble
.LSOverride

# Icon must end with two \r
Icon

# Thumbnails
._*

# Files that might appear in the root of a volume
.DocumentRevisions-V100
.fseventsd
.Spotlight-V100
.TemporaryItems
.Trashes
.VolumeIcon.icns
.com.apple.timemachine.donotpresent

# Directories potentially created on remote AFP share
.AppleDB
.AppleDesktop
Network Trash Folder
Temporary Items
.apdisk

### Windows ###
# Windows thumbnail cache files
Thumbs.db
Thumbs.db:encryptable
ehthumbs.db
ehthumbs_vista.db

# Dump file
*.stackdump

# Folder config file
[Dd]esktop.ini

# Recycle Bin used on file shares
$RECYCLE.BIN/

# Windows Installer files
*.cab
*.msi
*.msix
*.msm
*.msp

# Windows shortcuts
*.lnk

# End of https://www.gitignore.io/api/java,macos,windows,eclipse

.metadata/ 
Servers/ 
*.class 
*.classpath 
/target/ 
/bin/
/.settings/
/.apt_generated_tests/
[계산 pom.xml]
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
	<modelVersion>4.0.0</modelVersion>
	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.6.8</version>
		<relativePath /> <!-- lookup parent from repository -->
	</parent>
	<groupId>edu.global</groupId>
	<artifactId>ex</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<name>spring_boot_kdb_security</name>
	<description>Board project for Spring Boot</description>
	<properties>
		<java.version>11</java.version>
	</properties>
	<repositories>
		<repository>
			<id>oracle</id>
			<url>http://www.datanucleus.org/downloads/maven2/</url>
		</repository>
	</repositories>

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

		<!-- spring-boot-devtools는 클래스 수정시 웹서버를 재시작하여 결과를 바로 반영 -->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-devtools</artifactId>
			<scope>runtime</scope>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.projectlombok</groupId>
			<artifactId>lombok</artifactId>
			<optional>true</optional>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-tomcat</artifactId>
			<scope>provided</scope>
		</dependency>
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

		<!-- 오라클 JDBC 드라이버 -->
		<dependency>
			<groupId>oracle</groupId>
			<artifactId>ojdbc6</artifactId>
			<version>11.2.0.3</version>
		</dependency>

		<!-- MyBatis 라이브러리 -->
		<dependency>
			<groupId>org.mybatis.spring.boot</groupId>
			<artifactId>mybatis-spring-boot-starter</artifactId>
			<version>2.1.4</version>
		</dependency>

		<!-- MyBatis sql pretty -->
		<dependency>
			<groupId>org.bgee.log4jdbc-log4j2</groupId>
			<artifactId>log4jdbc-log4j2-jdbc4.1</artifactId>
			<version>1.16</version>
		</dependency>

		<!-- JSP를 사용하기 위한 라이브러리 -->
		<!-- 톰캣 파서 -->
		<dependency>
			<groupId>org.apache.tomcat.embed</groupId>
			<artifactId>tomcat-embed-jasper</artifactId>
		</dependency>

		<!-- jstl 라이브러리 -->
		<dependency>
			<groupId>javax.servlet</groupId>
			<artifactId>jstl</artifactId>
		</dependency>
	</dependencies>

	<build><!-- 컴파일~배포까지 -->
		<plugins>
			<plugin>
				<groupId>org.apache.tomcat.maven</groupId>
				<artifactId>tomcat7-maven-plugin</artifactId>
				<version>2.2</version>
				<configuration>
					<url>http://146.56.137.240:8282/manager/text</url>
					<username>admin</username>
					<password>1234</password>
				</configuration>
			</plugin>
			<!-- cmd에 입력 ( 배포 ) : mvnw.cmd tomcat7:redeploy -->
			<plugin>
				<groupId>org.springframework.boot</groupId>
				<artifactId>spring-boot-maven-plugin</artifactId>
				<configuration>
					<excludes>
						<exclude>
							<groupId>org.projectlombok</groupId>
							<artifactId>lombok</artifactId>
						</exclude>
					</excludes>
				</configuration>
			</plugin>
		</plugins>
	</build>
</project>
---------------------------------------------------------------------
[계산 application.properties]
#server port number
server.port = 8282

#datasource (oracle)
spring.datasource.driver-class-name=oracle.jdbc.driver.OracleDriver
spring.datasource.url=jdbc:oracle:thin:@localhost:1521/xe
#spring.datasource.driver-class-name=net.sf.log4jdbc.sql.jdbcapi.DriverSpy
#spring.datasource.url=jdbc:log4jdbc:oracle:thin:@localhost:1521/xe
spring.datasource.username=scott
spring.datasource.password=tiger

spring.devtools.livereload.enabled=true 

#jsp  
spring.mvc.view.prefix=/WEB-INF/views/
spring.mvc.view.suffix=.jsp
---------------------------------------------------------------------
[계산 HomeController.java]
package edu.global.ex.controller;

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

@Controller
public class HomeController {
	@GetMapping("/")
	public String home() {
		return "home";
	}
}
---------------------------------------------------------------------
[계산 home.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>Insert title here</title>
</head>
<body>
	home
</body>
</html>
---------------------------------------------------------------------
[계산 SecurityConfig.java]
package edu.global.ex.config;
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;

@Configuration // @Component + 의미(설정할 수 있는 파일)//(객체 생성해서 IOC컨테이너에 넣어라)
@EnableWebSecurity // 스프링 시큐리티 필터가 스프링 필터체인에 등록됨 = 스프링 시큐리티를 작동시키는 파일이라는 것을 알려줌 - 스프링한테.
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	@Override
	protected void configure(HttpSecurity http) throws Exception {
		// 우선 CSRF설정을 해제한다.
		// 초기 개발시만 해주는게 좋다.
		http.csrf().disable();
		http.authorizeRequests()
//	      .antMatchers("/user/**").hasAnyRole("USER") 
//	      .antMatchers("/admin/**").hasAnyRole("ADMIN")
//	      .antMatchers("/**").permitAll();
			.antMatchers("/**").hasAnyRole("ADMIN"); // id: admin, pw:admin

		http.formLogin(); // 스프링 시큐리티에 있는 기본 로그인 폼을 사용하겠다.
	}

	@Override
	protected void configure(AuthenticationManagerBuilder auth) throws Exception {
		auth.inMemoryAuthentication().withUser("user").password("{noop}user").roles("USER").and().withUser("admin")
				.password("{noop}admin").roles("ADMIN");
	}
}
[결과값]


0개의 댓글