新增示例auth、user、gateway、client
diff --git a/samples/client/pom.xml b/samples/client/pom.xml
new file mode 100644
index 0000000..a13d23a
--- /dev/null
+++ b/samples/client/pom.xml
@@ -0,0 +1,141 @@
+<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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>com.supwisdom.leaveschool</groupId>
+    <artifactId>samples-parent</artifactId>
+    <version>0.0.1-SNAPSHOT</version>
+  </parent>
+
+  <groupId>com.supwisdom.leaveschool</groupId>
+  <artifactId>sample-client</artifactId>
+  <packaging>jar</packaging>
+
+
+  <dependencies>
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter</artifactId>
+    </dependency>
+
+    <!-- 微服务 健康监控 -->
+    <!-- <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-actuator</artifactId>
+    </dependency> -->
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-web</artifactId>
+    </dependency>
+
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-mvc</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-object-mapper</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-i18n</artifactId>
+    </dependency>
+
+    <!-- 
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-lang</artifactId>
+    </dependency>
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-pinyin</artifactId>
+    </dependency>
+     -->
+
+
+    <dependency>
+      <groupId>com.supwisdom.infras</groupId>
+      <artifactId>infras-security</artifactId>
+    </dependency>
+
+    <!-- <dependency>
+      <groupId>org.springframework.security</groupId>
+      <artifactId>spring-security-cas</artifactId>
+    </dependency> -->
+
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-thymeleaf</artifactId>
+    </dependency>
+    <dependency>
+      <groupId>org.thymeleaf.extras</groupId>
+      <artifactId>thymeleaf-extras-springsecurity4</artifactId>
+    </dependency>
+
+
+
+    <!-- <dependency>
+      <groupId>org.springframework.cloud</groupId>
+      <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
+    </dependency> -->
+  
+    <dependency>
+      <groupId>org.springframework.cloud</groupId>
+      <artifactId>spring-cloud-starter-openfeign</artifactId>
+    </dependency>
+  
+    <dependency>
+      <groupId>org.springframework.cloud</groupId>
+      <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
+    </dependency>
+
+
+    <!-- Test things -->
+    <dependency>
+      <groupId>org.testng</groupId>
+      <artifactId>testng</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+    <dependency>
+      <groupId>org.springframework.boot</groupId>
+      <artifactId>spring-boot-starter-test</artifactId>
+      <scope>test</scope>
+    </dependency>
+
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-failsafe-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-javadoc-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-release-plugin</artifactId>
+      </plugin>
+      <plugin>
+        <groupId>org.jacoco</groupId>
+        <artifactId>jacoco-maven-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/ClientApplication.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/ClientApplication.java
new file mode 100644
index 0000000..b09fe05
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/ClientApplication.java
@@ -0,0 +1,17 @@
+package com.supwisdom.leaveschool.client;
+
+import org.springframework.boot.SpringApplication;
+import org.springframework.boot.autoconfigure.SpringBootApplication;
+import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
+import org.springframework.cloud.openfeign.EnableFeignClients;
+
+@SpringBootApplication
+@EnableCircuitBreaker
+@EnableFeignClients
+public class ClientApplication {
+
+  public static void main(String[] args) {
+    SpringApplication.run(ClientApplication.class, args);
+  }
+
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/Test.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/Test.java
new file mode 100644
index 0000000..6915296
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/Test.java
@@ -0,0 +1,9 @@
+package com.supwisdom.leaveschool.client;
+
+public class Test {
+
+  public static void main(String[] args) {
+    
+    
+  }
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/PasswordEncoderConfig.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/PasswordEncoderConfig.java
new file mode 100644
index 0000000..1fef80d
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/PasswordEncoderConfig.java
@@ -0,0 +1,30 @@
+package com.supwisdom.leaveschool.client.config;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.crypto.factory.PasswordEncoderFactories;
+import org.springframework.security.crypto.password.DelegatingPasswordEncoder;
+import org.springframework.security.crypto.password.NoOpPasswordEncoder;
+import org.springframework.security.crypto.password.PasswordEncoder;
+
+@Configuration
+public class PasswordEncoderConfig {
+  
+  private static final Logger logger = LoggerFactory.getLogger(PasswordEncoderConfig.class);
+  
+  @Bean
+  public PasswordEncoder passwordEncoder() {
+    
+    PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
+
+    if (passwordEncoder instanceof DelegatingPasswordEncoder) {
+      ((DelegatingPasswordEncoder)passwordEncoder).setDefaultPasswordEncoderForMatches(NoOpPasswordEncoder.getInstance());
+    }
+
+    logger.debug("PasswordEncoderConfig passwordEncoder is {}", passwordEncoder);
+    return passwordEncoder;
+  }
+
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/UserDetailsServiceConfig.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/UserDetailsServiceConfig.java
new file mode 100644
index 0000000..25253e3
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/config/UserDetailsServiceConfig.java
@@ -0,0 +1,23 @@
+package com.supwisdom.leaveschool.client.config;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.security.core.userdetails.UserDetailsService;
+
+import com.supwisdom.leaveschool.client.security.core.userdetails.MyUserDetailsService;
+
+@Configuration
+public class UserDetailsServiceConfig {
+
+  private static final Logger logger = LoggerFactory.getLogger(UserDetailsServiceConfig.class);
+  
+  @Bean
+  public UserDetailsService userDetailsService(MyUserDetailsService myUserDetailsService) throws Exception {
+    
+    logger.debug("UserDetailsServiceConfig userDetailsService is {}", myUserDetailsService);
+    return myUserDetailsService;
+  }
+  
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/controller/web/MainController.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/controller/web/MainController.java
new file mode 100755
index 0000000..217f944
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/controller/web/MainController.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2002-2016 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.supwisdom.leaveschool.client.controller.web;
+
+import org.springframework.stereotype.Controller;
+import org.springframework.ui.Model;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+@Controller
+public class MainController {
+
+	@RequestMapping("/")
+	public String root() {
+		return "redirect:/web/index";
+	}
+
+	@RequestMapping("/web/index")
+	public String index() {
+		return "web/index";
+	}
+
+	@RequestMapping(value = "/web/login")
+	public String login() {
+		return "web/login";
+	}
+
+	@RequestMapping(value = "/web/login", method = RequestMethod.POST)
+	public String postLogin() {
+		// TODO Enable form login with Spring Security (trigger error for now)
+		return "redirect:/web/login-error";
+	}
+
+	@RequestMapping("/web/login-error")
+	public String loginError(Model model) {
+		model.addAttribute("loginError", true);
+		return "web/login";
+	}
+
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/controller/web/admin/WebAdminUserController.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/controller/web/admin/WebAdminUserController.java
new file mode 100644
index 0000000..d3a3fb0
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/controller/web/admin/WebAdminUserController.java
@@ -0,0 +1,38 @@
+package com.supwisdom.leaveschool.client.controller.web.admin;
+
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.RequestMapping;
+
+import com.supwisdom.leaveschool.client.service.UserRemoteService;
+import com.supwisdom.leaveschool.client.util.AuthenticationUtil;
+
+@Controller
+@RequestMapping("/web/admin/user")
+public class WebAdminUserController {
+  
+  private static final Logger logger = LoggerFactory.getLogger(WebAdminUserController.class);
+
+  @Autowired
+  UserRemoteService userRemoteService;
+
+  @RequestMapping("/index")
+  public String userIndex() {
+    
+    logger.debug(AuthenticationUtil.currentUsername());
+    
+    Map<String, Object> map = userRemoteService.greeting("abcd");
+    if (map != null) {
+      logger.debug("message is " + map.get("message"));
+    } else {
+      logger.debug("message is null");
+    }
+    
+    return "web/admin/user/index";
+  }
+
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/core/userdetails/MyUser.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/core/userdetails/MyUser.java
new file mode 100644
index 0000000..dc3a27b
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/core/userdetails/MyUser.java
@@ -0,0 +1,30 @@
+package com.supwisdom.leaveschool.client.security.core.userdetails;
+
+import java.util.Collection;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.userdetails.User;
+
+public class MyUser extends User {
+  
+  //private static final Log logger = LogFactory.getLog(MyUser.class);
+  private static final Logger logger = LoggerFactory.getLogger(MyUser.class);
+
+  /**
+   * 
+   */
+  private static final long serialVersionUID = 5438858716934315373L;
+  
+  public MyUser(String username, String password,
+      Collection<? extends GrantedAuthority> authorities) {
+    this(username, password, true, true, true, true, authorities);
+  }
+
+  public MyUser(String username, String password, boolean enabled, boolean accountNonExpired,
+      boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities) {
+    super(username, password, enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, authorities);
+  }
+
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/core/userdetails/MyUserDetailsService.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/core/userdetails/MyUserDetailsService.java
new file mode 100644
index 0000000..5cecb9d
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/security/core/userdetails/MyUserDetailsService.java
@@ -0,0 +1,41 @@
+package com.supwisdom.leaveschool.client.security.core.userdetails;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.core.authority.SimpleGrantedAuthority;
+import org.springframework.security.core.userdetails.UserDetails;
+import org.springframework.security.core.userdetails.UserDetailsService;
+import org.springframework.security.core.userdetails.UsernameNotFoundException;
+import org.springframework.security.crypto.password.PasswordEncoder;
+import org.springframework.stereotype.Service;
+
+@Service
+public class MyUserDetailsService implements UserDetailsService {
+  
+  //private static final Log logger = LogFactory.getLog(MyUserDetailsService.class);
+  private static final Logger logger = LoggerFactory.getLogger(MyUserDetailsService.class);
+  
+  @Autowired
+  PasswordEncoder passwordEncoder;
+  
+  @Override
+  public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
+    
+    logger.debug("MyUserDetailsService.loadUserByUsername({})", username);
+    
+    // TODO: 从数据库获取
+    List<GrantedAuthority> authorities = new ArrayList<GrantedAuthority>();
+    authorities.add(new SimpleGrantedAuthority("ROLE_USER"));
+    
+    MyUser myUser = new MyUser("user", passwordEncoder.encode("password"), authorities);
+    logger.debug("myUser is {}", myUser);
+    
+    return myUser;
+  }
+
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/service/UserRemoteService.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/service/UserRemoteService.java
new file mode 100644
index 0000000..5a64da2
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/service/UserRemoteService.java
@@ -0,0 +1,23 @@
+package com.supwisdom.leaveschool.client.service;
+
+import java.util.Map;
+
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.util.MimeTypeUtils;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+
+import com.supwisdom.leaveschool.client.service.fallback.UserRemoteHystrix;
+
+@FeignClient(
+    name = "sample-user", 
+    url = "${gateway.api.url}/sample-user/admin/users", 
+    fallback = UserRemoteHystrix.class
+)
+public interface UserRemoteService {
+
+  @RequestMapping(method = RequestMethod.GET, value = "/greeting/{name}", produces = MimeTypeUtils.APPLICATION_JSON_VALUE)
+  Map<String, Object> greeting(@PathVariable("name") String name);
+  
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/service/fallback/UserRemoteHystrix.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/service/fallback/UserRemoteHystrix.java
new file mode 100644
index 0000000..7a2846c
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/service/fallback/UserRemoteHystrix.java
@@ -0,0 +1,22 @@
+package com.supwisdom.leaveschool.client.service.fallback;
+
+import java.util.Map;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Component;
+
+import com.supwisdom.leaveschool.client.service.UserRemoteService;
+
+@Component
+public class UserRemoteHystrix implements UserRemoteService {
+  
+  private static final Logger logger = LoggerFactory.getLogger(UserRemoteHystrix.class);
+
+  @Override
+  public Map<String, Object> greeting(String name) {
+    logger.debug("greeting failure!");
+    return null;
+  }
+
+}
diff --git a/samples/client/src/main/java/com/supwisdom/leaveschool/client/util/AuthenticationUtil.java b/samples/client/src/main/java/com/supwisdom/leaveschool/client/util/AuthenticationUtil.java
new file mode 100644
index 0000000..438477b
--- /dev/null
+++ b/samples/client/src/main/java/com/supwisdom/leaveschool/client/util/AuthenticationUtil.java
@@ -0,0 +1,44 @@
+package com.supwisdom.leaveschool.client.util;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+
+import com.supwisdom.leaveschool.client.security.core.userdetails.MyUser;
+
+public class AuthenticationUtil {
+
+  private static final Logger logger = LoggerFactory.getLogger(AuthenticationUtil.class);
+
+  public static String currentUsername() {
+
+    Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+
+    if (authentication == null) {
+      logger.error("authentication is null");
+      return null;
+    }
+
+    logger.debug("authentication is {}", authentication.getPrincipal());
+
+    if (!authentication.isAuthenticated()) {
+      logger.error("authentication is not authenticated");
+      return null;
+    }
+
+    if (authentication.getPrincipal() == null) {
+      logger.error("authentication's principal is null");
+      return null;
+    }
+
+    logger.debug("authentication's principal is {}", authentication.getPrincipal());
+
+    if (authentication.getPrincipal() instanceof MyUser) {
+      return ((MyUser) authentication.getPrincipal()).getUsername();
+    }
+
+    return null;
+  }
+
+}
diff --git a/samples/client/src/main/resources/application.yml b/samples/client/src/main/resources/application.yml
new file mode 100755
index 0000000..550499b
--- /dev/null
+++ b/samples/client/src/main/resources/application.yml
@@ -0,0 +1,39 @@
+server:
+  port: 8080
+
+## logging
+logging:
+  level:
+    root: INFO
+    org.springframework.web: INFO
+    org.springframework.cloud.openfeign: TRACE
+    com.supwisdom.infras.security: DEBUG
+    com.supwisdom.leaveschool: DEBUG
+
+spring:
+  application:
+    name: sample-client
+  thymeleaf:
+    cache: false
+
+feign:
+  client:
+    config:
+      default:
+        connectTimeout: 60000
+        readTimeout: 60000
+        loggerLevel: full
+  hystrix:
+    enabled: true
+
+hystrix:
+  command:
+    default:
+      execution:
+        timeout:
+          enabled: true
+        isolation:
+          thread:
+            timeoutInMilliseconds: 60000
+
+gateway.api.url: http://localhost:5555/api
diff --git a/samples/client/src/main/resources/static/assets/css/CSS b/samples/client/src/main/resources/static/assets/css/CSS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/samples/client/src/main/resources/static/assets/css/CSS
diff --git a/samples/client/src/main/resources/static/assets/css/main.css b/samples/client/src/main/resources/static/assets/css/main.css
new file mode 100755
index 0000000..5e6687a
--- /dev/null
+++ b/samples/client/src/main/resources/static/assets/css/main.css
@@ -0,0 +1,13 @@
+body {
+    font-family: sans;
+    font-size: 1em;
+}
+
+p.error {
+    font-weight: bold;
+    color: red;
+}
+
+div.logout {
+    float: right;
+}
\ No newline at end of file
diff --git a/samples/client/src/main/resources/static/assets/images/IMAGES b/samples/client/src/main/resources/static/assets/images/IMAGES
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/samples/client/src/main/resources/static/assets/images/IMAGES
diff --git a/samples/client/src/main/resources/static/assets/js/JS b/samples/client/src/main/resources/static/assets/js/JS
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/samples/client/src/main/resources/static/assets/js/JS
diff --git a/samples/client/src/main/resources/templates/web/admin/user/index.html b/samples/client/src/main/resources/templates/web/admin/user/index.html
new file mode 100644
index 0000000..2326203
--- /dev/null
+++ b/samples/client/src/main/resources/templates/web/admin/user/index.html
@@ -0,0 +1,15 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
+<head>
+<title>Hello Spring Security</title>
+<meta charset="utf-8" />
+<link rel="stylesheet" href="/assets/css/main.css" th:href="@{/assets/css/main.css}" />
+</head>
+<body>
+  <div th:substituteby="web/index::logout"></div>
+  <h1>This is a secured page!</h1>
+  <p>
+    <a href="/web/index" th:href="@{/web/index}">Back to home page</a>
+  </p>
+</body>
+</html>
\ No newline at end of file
diff --git a/samples/client/src/main/resources/templates/web/index.html b/samples/client/src/main/resources/templates/web/index.html
new file mode 100644
index 0000000..b9dcbf4
--- /dev/null
+++ b/samples/client/src/main/resources/templates/web/index.html
@@ -0,0 +1,26 @@
+<!DOCTYPE HTML>
+<!-- <html xmlns:th="http://www.thymeleaf.org"> -->
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
+<head>
+<title>Hello Spring Security</title>
+<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
+<meta charset="utf-8" />
+<link rel="stylesheet" href="/assets/css/main.css" th:href="@{/assets/css/main.css}" />
+</head>
+<body>
+  <div th:fragment="logout" class="logout" sec:authorize="isAuthenticated()">
+    Logged in user: <span sec:authentication="name"></span> | 
+    Roles: <span sec:authentication="principal.authorities"></span>
+    <div>
+      <form action="#" th:action="@{/web/logout}" method="post">
+        <input type="submit" value="Logout" />
+      </form>
+    </div>
+  </div>
+  <h1>Hello Spring Security</h1>
+  <p>This is an unsecured page, but you can access the secured pages after authenticating.</p>
+  <ul>
+    <li>Go to the <a href="/web/admin/user/index" th:href="@{/web/admin/user/index}">secured pages</a></li>
+  </ul>
+</body>
+</html>
diff --git a/samples/client/src/main/resources/templates/web/login.html b/samples/client/src/main/resources/templates/web/login.html
new file mode 100755
index 0000000..1bc5e4d
--- /dev/null
+++ b/samples/client/src/main/resources/templates/web/login.html
@@ -0,0 +1,24 @@
+<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org">
+    <head>
+        <title>Login page</title>
+        <meta charset="utf-8" />
+        <link rel="stylesheet" href="/assets/css/main.css" th:href="@{/assets/css/main.css}" />
+	</head>
+    <body>
+        <h1>Login page</h1>
+        <p>Example user: user / password</p>
+        <p th:if="${loginError}" class="error">Wrong user or password</p>
+        <div th:if="${param.error}" class="alert alert-error">Invalid username and password.</div>
+        <div th:if="${param.logout}" class="alert alert-success">You have been logged out.</div>
+        
+        <form th:action="@{/web/login}" method="post">
+            <label for="username">Username</label>:
+            <input type="text" id="username" name="username" autofocus="autofocus" /> <br />
+            <label for="password">Password</label>:
+            <input type="password" id="password" name="password" /> <br />
+            <input type="submit" value="Log in" />
+        </form>
+        <p><a href="/index" th:href="@{/index}">Back to home page</a></p>
+    </body>
+</html>