이 문서는 가리사니 개발자 포럼에 올렸던 글의 백업 파일입니다. 오래된 문서가 많아 현재 상황과 맞지 않을 수 있습니다.
머스터치
공식 : https://mustache.github.io/ 데모 : https://mustache.github.io/#demo
- 을 통해 빠른 치환 장점
- 웬만한 플랫폼을 모두 지원한다.
- 속도가 빠르다. 단점
- 플랫폼 공용으로 만들어졌기에 스프링 같은 곳에서 쓰기위해서는 모두 모델안에 넣어줘야한다.
- 상위를 선택하는 방법이 한정적임.
문법
예제 데이터
{
"header": "Colors",
"items": [
{"name": "red", "first": true, "url": "#Red"},
{"name": "green", "link": true, "url": "#Green"},
{"name": "blue", "link": true, "url": "#Blue"}
],
"empty": false
}
출력
IF
- NOT (^)을 제외하면 루프와 동일
- (^) 제외시 IF 개념이 아니라 반복 이지만 이해를 돕기위한 설명입니다. ``` java
해더가 존재함
``` java
해더가 존재하지 않음
해더333 이 존재하지 않음
내부출력 - 자기자신
해드의 값은 임
루프 : 사실상 위 IF 가 루프를 통하고있다.
-
즉 배열형이면 루프를 돌며 출력되며, 배열이 아닌 값이면 단일 출력이되며, 값이 없으면 출력되지않음. ``` java
content<div class="post title">[백업][가리사니] spring boot security : 5. 회원가입</div>
이 문서는 가리사니 개발자 포럼에 올렸던 글의 백업 파일입니다. 오래된 문서가 많아 현재 상황과 맞지 않을 수 있습니다.
Spring boot Security 시리즈
- 1. 설치 및 페이지 설정
- 2. 인증로직을 만들어보자.
- 3. 인증로직 - 잠재적 위험
- 4. 인증 페이지뷰
- 5. 회원가입
- 부록 : Spring Security login (성공 / 실패) 이벤트 리스너
뷰
2장 강의에선 string 으로 뽑았던 메인페이지도 새로 만들어줍니다. src/main/resources/templates/main.html
<!DOCTYPE html>
<html xmlns:th="http://www.typeleaf.org">
<head>
<meta charset="utf-8"/>
<title>메인페이지</title>
</head>
<body>
<div>
<a href="/mypage">마이페이지</a><br/>
<a href="/login">로그인</a><br/>
<a href="/create">회원가입</a><br/>
</div>
</body>
</html>
src/main/resources/templates/create.html
<!DOCTYPE html>
<html xmlns:th="http://www.typeleaf.org">
<head>
<meta charset="utf-8"/>
<title>회원가입</title>
</head>
<body>
<div>
<form th:action="@{/createProcessing}" method="post">
<h2>회원가입</h2>
<!-- 강의를 간결하게 끝내기 위함.. 원래는 가입실패 여부를 자세히 표시해야한다 -->
<div th:if="${param.error}">
계정이 중복됩니다.
</div>
<input type="text" name="ac" placeholder="계정" required="required"/>
<input type="password" name="pw" placeholder="암호" required="required"/>
<input type="submit" value="회원가입"/>
</form>
</div>
</body>
</html>
서비스
@Component
public class AccountService
{
@Autowired
AccountRepository accountRepository;
// 리턴을 저런식으로하면 안됩니다.
// (무었때문에 가입 실패했는지를 적어주셔야..)
@Transactional
public boolean create(String ac, String pw)
{
if (accountRepository.findOneByAc(ac) != null)
{
return false;
}
Account account = new Account();
account.setAc(ac);
account.setPw(new BCryptPasswordEncoder().encode(pw));
account.setRole("NORMAL");
accountRepository.save(account);
return true;
}
public Account getAccount(String ac)
{
return accountRepository.findOneByAc(ac);
}
}
컨트롤러
@RequestMapping("/")
String main()
{
return "main";
}
@RequestMapping("/create")
String create()
{
return "create";
}
@Autowired
AccountService accountService;
@RequestMapping("/createProcessing")
String createProcessing(@Param("ac") String ac, @Param("ac") String pw)
{
if (accountService.create(ac, pw))
{
return "redirect:/login";
}
else
{
return "redirect:/create?error";
}
}
권한설정
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
// 회원가입과 처리부분이 추가
.antMatchers("/login", "/create", "/createProcessing").permitAll()
.antMatchers("/**").authenticated();
http
.formLogin()
// 로그인 처리 페이지
.loginProcessingUrl("/loginProcessing")
// 로그인 페이지
.loginPage("/login")
.failureUrl("/login?error");
http
.logout()
// /logout 을 호출할 경우 로그아웃
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
// 로그아웃이 성공했을 경우 이동할 페이지
.logoutSuccessUrl("/");
}
요약 - 결론
회원가입시 암호를 넣을 때 로그인에 적용한 동일한 해시를 적용하시면 됩니다.
추신
처음엔 연동부부만 쓰려다가 조금 더 확장하니…. 소스가 난장판이 되었습니다.;;;;; 다듬어서 다시 쓰려고했지만… 요즘 시간이 부족하네요 ㅠㅠ…;;;
<li><strong></strong></li> content<div class="post title">[백업][가리사니] spring boot security : 5. 회원가입</div>
이 문서는 가리사니 개발자 포럼에 올렸던 글의 백업 파일입니다. 오래된 문서가 많아 현재 상황과 맞지 않을 수 있습니다.
Spring boot Security 시리즈
- 1. 설치 및 페이지 설정
- 2. 인증로직을 만들어보자.
- 3. 인증로직 - 잠재적 위험
- 4. 인증 페이지뷰
- 5. 회원가입
- 부록 : Spring Security login (성공 / 실패) 이벤트 리스너
뷰
2장 강의에선 string 으로 뽑았던 메인페이지도 새로 만들어줍니다. src/main/resources/templates/main.html
<!DOCTYPE html>
<html xmlns:th="http://www.typeleaf.org">
<head>
<meta charset="utf-8"/>
<title>메인페이지</title>
</head>
<body>
<div>
<a href="/mypage">마이페이지</a><br/>
<a href="/login">로그인</a><br/>
<a href="/create">회원가입</a><br/>
</div>
</body>
</html>
src/main/resources/templates/create.html
<!DOCTYPE html>
<html xmlns:th="http://www.typeleaf.org">
<head>
<meta charset="utf-8"/>
<title>회원가입</title>
</head>
<body>
<div>
<form th:action="@{/createProcessing}" method="post">
<h2>회원가입</h2>
<!-- 강의를 간결하게 끝내기 위함.. 원래는 가입실패 여부를 자세히 표시해야한다 -->
<div th:if="${param.error}">
계정이 중복됩니다.
</div>
<input type="text" name="ac" placeholder="계정" required="required"/>
<input type="password" name="pw" placeholder="암호" required="required"/>
<input type="submit" value="회원가입"/>
</form>
</div>
</body>
</html>
서비스
@Component
public class AccountService
{
@Autowired
AccountRepository accountRepository;
// 리턴을 저런식으로하면 안됩니다.
// (무었때문에 가입 실패했는지를 적어주셔야..)
@Transactional
public boolean create(String ac, String pw)
{
if (accountRepository.findOneByAc(ac) != null)
{
return false;
}
Account account = new Account();
account.setAc(ac);
account.setPw(new BCryptPasswordEncoder().encode(pw));
account.setRole("NORMAL");
accountRepository.save(account);
return true;
}
public Account getAccount(String ac)
{
return accountRepository.findOneByAc(ac);
}
}
컨트롤러
@RequestMapping("/")
String main()
{
return "main";
}
@RequestMapping("/create")
String create()
{
return "create";
}
@Autowired
AccountService accountService;
@RequestMapping("/createProcessing")
String createProcessing(@Param("ac") String ac, @Param("ac") String pw)
{
if (accountService.create(ac, pw))
{
return "redirect:/login";
}
else
{
return "redirect:/create?error";
}
}
권한설정
@Override
protected void configure(HttpSecurity http) throws Exception
{
http.authorizeRequests()
// 회원가입과 처리부분이 추가
.antMatchers("/login", "/create", "/createProcessing").permitAll()
.antMatchers("/**").authenticated();
http
.formLogin()
// 로그인 처리 페이지
.loginProcessingUrl("/loginProcessing")
// 로그인 페이지
.loginPage("/login")
.failureUrl("/login?error");
http
.logout()
// /logout 을 호출할 경우 로그아웃
.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
// 로그아웃이 성공했을 경우 이동할 페이지
.logoutSuccessUrl("/");
}
요약 - 결론
회원가입시 암호를 넣을 때 로그인에 적용한 동일한 해시를 적용하시면 됩니다.
추신
처음엔 연동부부만 쓰려다가 조금 더 확장하니…. 소스가 난장판이 되었습니다.;;;;; 다듬어서 다시 쓰려고했지만… 요즘 시간이 부족하네요 ㅠㅠ…;;;
<li><a href=""></a></li>
주석
``` java
상위선택
- 상위를 선택하는 문법이 한정적임
- 이렇게 사용할 경우 items 안에 해더가 없을때 한단계 위 해더가 선택된다.
- 단계별로 올라가도 끝내 해더가 나오지 않을 경우 빈값 ``` java
포함 : include
- 해당 경로에 있는 템플릿을 결합합니다.
``` java
스프링에서 적용하기
메이븐 추가
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-mustache</artifactId>
</dependency>
src/main/resources/templates/test.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title></title>
</head>
<body>
<div>
</div>
</body>
</html>
컨트롤러
@RequestMapping("/")
public String root(Model model)
{
model.setAttribute("title", "타이틀 테스트");
model.setAttribute("msg", "Hello!!");
return "test";
}
연동이 안되는 경우는 아래와 같이 리졸버를 등록해보세요.
@Configuration
public class WebConfiguration implements WebMvcConfigurer {
@Override
public void configureViewResolvers(ViewResolverRegistry registry) {
MustacheViewResolver resolver = new MustacheViewResolver();
resolver.setCharset("UTF-8");
resolver.setContentType("text/html;charset=UTF-8");
resolver.setPrefix("classpath:/templates/");
resolver.setSuffix(".html");
registry.viewResolver(resolver);
}
}