diff --git a/README.md b/README.md
index 416da02..d86ed90 100644
--- a/README.md
+++ b/README.md
@@ -5,6 +5,7 @@
 
 项目用Maven管理, 字符编码: UTF-8
 
+<em>授权协议:<a href="https://gitee.com/shengzhao/spring-oauth-server/tree/master/LICENSE">GPL-2.0</a></em>
 
 使用的技术与版本号
 <ol>
@@ -17,22 +18,26 @@
  <li>MySQL (5.6.23)</li>
  <li>EhCache (2.0.4)</li>
 </ol>
+<h4>技术视频</h4>
+<a href="http://list.youku.com/albumlist/show/id_51900110.html" target="_blank">http://list.youku.com/albumlist/show/id_51900110.html</a>
+(持续更新...)
+
 <hr/>
 
-<strong>Java Config版本请访问Branch: <a href="http://git.oschina.net/shengzhao/spring-oauth-server/tree/config/">config</a></strong>
+<h3>Spring-Boot版本请访问Branch: <a href="https://gitee.com/shengzhao/spring-oauth-server/tree/config/">config</a></h3>
 
-<strong>MongoDB版本请访问Branch: <a href="http://git.oschina.net/shengzhao/spring-oauth-server/tree/mongodb/">mongodb</a></strong>
+<strong>MongoDB版本请访问Branch: <a href="https://gitee.com/shengzhao/spring-oauth-server/tree/mongodb/">mongodb</a></strong>
 
 <strong>OAuth2下一代身份认证授权协议OIDC实现: <a href="https://git.oschina.net/mkk/MyOIDC">MyOIDC</a></strong>
 <hr/>
 <h3>
-   OAuth2客户端项目请访问 <a href="http://git.oschina.net/mkk/spring-oauth-client">spring-oauth-client</a>
+   OAuth2客户端项目请访问 <a href="https://gitee.com/mkk/spring-oauth-client">spring-oauth-client</a>
 </h3>
 <h3>
    在线测试访问地址 <a href="http://andaily.com/spring-oauth-server/">http://andaily.com/spring-oauth-server/</a>
 </h3>
 <h4>
-   Shiro与OLTU整合的OAuth2项目 <a href="http://git.oschina.net/mkk/oauth2-shiro">http://git.oschina.net/mkk/oauth2-shiro</a>
+   Shiro与OLTU整合的OAuth2项目 <a href="https://gitee.com/mkk/oauth2-shiro">https://gitee.com/mkk/oauth2-shiro</a><br/>
    (相比spring-oauth-server, 该项目入门门槛相对较低, 代码更加透明, 理解更容易,可扩展性更强, 且模块化开发)
 </h4>
 <hr/>
@@ -44,7 +49,7 @@
 项目是Maven管理的, 需要本地安装maven(开发用的maven版本号为3.1.0), 还有MySql(开发用的mysql版本号为5.6)
 </li>
 <li>
-<a href="http://git.oschina.net/shengzhao/spring-oauth-server/repository/archive?ref=master">下载</a>(或clone)项目到本地
+<a href="https://gitee.com/shengzhao/spring-oauth-server/repository/archive?ref=master">下载</a>(或clone)项目到本地
 </li>
 <li>
 创建MySQL数据库(如数据库名oauth2), 并运行相应的SQL脚本(脚本文件位于others/database目录),
@@ -52,7 +57,7 @@
    运行脚本的顺序: initial_db.ddl -> oauth.ddl -> initial_data.ddl
 </li>
 <li>
-修改<a href="http://git.oschina.net/shengzhao/spring-oauth-server/blob/master/src/main/resources/spring-oauth-server.properties">spring-oauth-server.properties</a>(位于src/main/resources目录)中的数据库连接信息(包括username, password等)
+修改<a href="https://gitee.com/shengzhao/spring-oauth-server/blob/master/src/main/resources/spring-oauth-server.properties">spring-oauth-server.properties</a>(位于src/main/resources目录)中的数据库连接信息(包括username, password等)
 </li>
 <li>
 将本地项目导入到IDE(如Intellij IDEA)中,配置Tomcat(或类似的servlet运行服务器), 并启动Tomcat(默认端口为8080);
@@ -63,7 +68,7 @@
          将war放在Tomcat中并启动(注意: 这种方式需要将spring-oauth-server.properties加入到classpath中并正确配置数据库连接信息).
 </li>
 <li>
-参考<a href="http://git.oschina.net/shengzhao/spring-oauth-server/blob/master/others/oauth_test.txt">oauth_test.txt</a>(位于others目录)的内容并测试之(也可在浏览器中访问相应的地址,如: http://localhost:8080/spring-oauth-server).
+参考<a href="https://gitee.com/shengzhao/spring-oauth-server/blob/master/others/oauth_test.txt">oauth_test.txt</a>(位于others目录)的内容并测试之(也可在浏览器中访问相应的地址,如: http://localhost:8080/spring-oauth-server).
 </li>
 </ol>
 </p>
@@ -93,8 +98,8 @@
 </li>
 <li>
 <p>
- 如果在使用过程中遇到特殊的问题(如:如何将oauth_code存入数据库),请访问项目的 <a href="http://git.oschina.net/shengzhao/spring-oauth-server/wikis/pages">Wiki</a> 
- 与 <a href="http://git.oschina.net/shengzhao/spring-oauth-server/attach_files">附件</a>. 
+ 如果在使用过程中遇到特殊的问题(如:如何将oauth_code存入数据库),请访问项目的 <a href="https://gitee.com/shengzhao/spring-oauth-server/wikis/pages">Wiki</a> 
+ 与 <a href="https://gitee.com/shengzhao/spring-oauth-server/attach_files">附件</a>. 
  <br/>
  我会把大家反馈的问题解决办法添加在这里.
  <br/>
@@ -105,7 +110,7 @@
 
 <li>
 <p>
- 如果在使用项目的过程中发现任何的BUG或者更好的提议, 建议将其提交到项目的 <a href="http://git.oschina.net/shengzhao/spring-oauth-server/issues">Issues</a> 中, 
+ 如果在使用项目的过程中发现任何的BUG或者更好的提议, 建议将其提交到项目的 <a href="https://gitee.com/shengzhao/spring-oauth-server/issues">Issues</a> 中, 
  我会一直关注并不断改进项目. 
 </p>
 </li>
@@ -115,10 +120,10 @@
 <strong>功能扩展</strong>
 <ol>
     <li>
-        <code>oauth_code存入数据库的配置</code>,  请下载文件 <a href="http://git.oschina.net/shengzhao/spring-oauth-server/attach_files">oauth_code存入数据库的配置.jpg</a>
+        <code>oauth_code存入数据库的配置</code>,  请下载文件 <a href="https://gitee.com/shengzhao/spring-oauth-server/attach_files">oauth_code存入数据库的配置.jpg</a>
     </li>
     <li>
-        <code>改变token过期的时间的配置</code>, 请下载文件<a href="http://git.oschina.net/shengzhao/spring-oauth-server/attach_files">改变token过期的时间的配置.jpg</a>
+        <code>改变token过期的时间的配置</code>, 请下载文件<a href="https://gitee.com/shengzhao/spring-oauth-server/attach_files">改变token过期的时间的配置.jpg</a>
     </li>
     <li>
         <code>自定义 grant_type</code>, 默认情况支持的grant_type包括 [password,authorization_code,refresh_token,implicit], 若不需要其中的某些grant_type,
@@ -152,14 +157,40 @@
 <p>
 从 0.3版本开始将项目的所有计划的开发内容列出来, 方便大家跟进, 也欢迎你加入.
 <br/>
-项目的开发管理使用开源项目 <a href="http://git.oschina.net/mkk/andaily-developer">andaily-developer</a>.
+项目的开发管理使用开源项目 <a href="https://gitee.com/mkk/andaily-developer">andaily-developer</a>.
 </p>
 <ul>
        <li>
             <p>
-                Version: <strong>1.0</strong> [pending]
+                Version: <strong>2.0.1</strong> [pending]
                 <br/>
-                Date: 2017-03-30 / ---
+                Date: 2018-05-01 / ---
+            </p>
+            <ol>
+                <li><p>增加 /oauth/check_token 可使用   #IJO9H</p></li>
+                <li><p><del>Fix issue   #IJO9R  /oauth/rest_token 接口 client_secret字段没有校验</del></p></li>
+                <li><p><del>升级spring-boot 版本为 2.0.2.RELEASE</del></p></li>
+                <li><p><del>将项目用视频方式展现出来,更直观.  <a href="http://list.youku.com/albumlist/show/id_51900110.html" target="_blank>视频链接</a></del></p></li>
+            </ol>
+            <br/>
+       </li>       
+       <li>
+            <p>
+                Version: <strong>2.0.0</strong> [finished]
+                <br/>
+                Date: 2018-04-09 / 2018-04-21
+            </p>
+            <ol>
+                <li><p><del>更新UI,为了更易理解与使用,场景化</del></p></li>
+                <li><strong><del>使用 spring-boot 重构</del></strong></li>
+            </ol>
+            <br/>
+       </li>
+       <li>
+            <p>
+                Version: <strong>1.0</strong> [finished]
+                <br/>
+                Date: 2017-03-30 / 2018-04-04
             </p>
             <ol>
                 <li><p><del>implicit测试时 取消掉 client secret</del></p></li>
@@ -227,7 +258,7 @@
             <ol>
                 <li><p>#73 - Upgrade 'spring-security-oauth2' version to '2.0.6.RELEASE' (current: 1.0.5.RELEASE)      [CANCELED]</p></li>
                 <li><p><del>#74 - oauth mysql ddl add create_time,  default is now()  </del></p></li>
-                <li><p><del>#75 - Add user information API, for <a href="http://git.oschina.net/mkk/spring-oauth-client"><code>spring-oauth-client</code></a> project use
+                <li><p><del>#75 - Add user information API, for <a href="https://gitee.com/mkk/spring-oauth-client"><code>spring-oauth-client</code></a> project use
         <pre>
         URL: /unity/user_info
         Login: Yes (ROLE_UNITY)
@@ -266,23 +297,24 @@
 <p>
     <ol>
         <li><p><em>2013-11-19</em>     Initial project, start push code</p></li>
-        <li><p><em>2013-11-20</em>     发布<a href="http://git.oschina.net/shengzhao/spring-oauth-server/tree/0.1/">0.1</a>版本</p></li>
+        <li><p><em>2013-11-20</em>     发布<a href="https://gitee.com/shengzhao/spring-oauth-server/tree/0.1/">0.1</a>版本</p></li>
         <li><p><em>2015-05-06</em>        发布<a href="http://www.oschina.net/news/62176/spring-oauth-server-0-2">0.2</a>版本</p></li>
         <li><p><em>2015-05-27</em>      创建项目博客,访问地址 <a href="http://andaily.com/blog/?cat=19">http://andaily.com/blog/?cat=19</a></p></li>
-        <li><p><em>2015-06-07</em>        发布<a href="http://git.oschina.net/shengzhao/spring-oauth-server/tree/0.3/">0.3</a>版本</p></li>
+        <li><p><em>2015-06-07</em>        发布<a href="https://gitee.com/shengzhao/spring-oauth-server/tree/0.3/">0.3</a>版本</p></li>
         <li><p>
             <em>2015-06-16</em>       添加github访问: <a href="https://github.com/monkeyk/spring-oauth-server">https://github.com/monkeyk/spring-oauth-server</a>,
             以后的更新将同步github与gitosc.
         </p></li>
         <li><p><em>2015-11-09</em>        开始开发 0.4-beta 版本</p></li>
-        <li><p><em>2015-11-18</em>        发布 <a href="http://git.oschina.net/shengzhao/spring-oauth-server/tree/0.4-beta/">0.4-beta</a> 版本</p></li>
-        <li><p><em>2016-01-02</em>        发布 <a href="http://git.oschina.net/shengzhao/spring-oauth-server/tree/0.4/">0.4</a> 版本</p></li>
+        <li><p><em>2015-11-18</em>        发布 <a href="https://gitee.com/shengzhao/spring-oauth-server/tree/0.4-beta/">0.4-beta</a> 版本</p></li>
+        <li><p><em>2016-01-02</em>        发布 <a href="https://gitee.com/shengzhao/spring-oauth-server/tree/0.4/">0.4</a> 版本</p></li>
         <li><p><em>2016-02-19</em>        Add 0.5 version development planning</p></li>
-        <li><p><em>2016-04-03</em>        Add <a href="http://git.oschina.net/shengzhao/spring-oauth-server/tree/config/">config</a> branch</p></li>
-        <li><p><em>2016-04-14</em>        Add <a href="http://git.oschina.net/shengzhao/spring-oauth-server/tree/mongodb/">mongodb</a> branch</p></li>
-        <li><p><em>2016-06-02</em>        发布 <a href="http://git.oschina.net/shengzhao/spring-oauth-server/tree/0.5/">0.5</a> 版本</p></li>
+        <li><p><em>2016-04-03</em>        Add <a href="https://gitee.com/shengzhao/spring-oauth-server/tree/config/">config</a> branch</p></li>
+        <li><p><em>2016-04-14</em>        Add <a href="https://gitee.com/shengzhao/spring-oauth-server/tree/mongodb/">mongodb</a> branch</p></li>
+        <li><p><em>2016-06-02</em>        发布 <a href="https://gitee.com/shengzhao/spring-oauth-server/tree/0.5/">0.5</a> 版本</p></li>
         <li><p><em>2016-07-06</em>        Add 0.6 version planning</p></li>
         <li><p><em>2016-10-13</em>        发布0.6版本</p></li>
+        <li><p><em>2018-04-21</em>        发布2.0.0版本, <a href="https://gitee.com/shengzhao/spring-oauth-server/tree/config/" target="_blank">spring-boot版本</a></p></li>
     </ol>
 </p>
 
@@ -359,6 +391,9 @@
     与项目相关的,与OAuth2相关的问题与回答,以及各类讨论请访问<br/>
     <a href="http://andaily.com/blog/?dwqa-question_category=oauth">http://andaily.com/blog/?dwqa-question_category=oauth</a>
 </p>
+<p>
+    GitHub项目地址: <a href="https://github.com/monkeyk/spring-oauth-server.git">https://github.com/monkeyk/spring-oauth-server.git</a>
+</p>
 
 
 <hr/>
@@ -388,6 +423,7 @@
         <li><p>南京索特科技 -- 200元 (2016-12-16)</p></li>
         <li><p>周广文 -- 6.66元 (2017-02-17)</p></li>
         <li><p>境随心转 -- 20元 (2017-06-09)</p></li>
+        <li><p>Xyz(秦) -- 50元 (2018-06-05)</p></li>
     </ul>
 </div>
 
diff --git a/src/main/java/com/monkeyk/sos/infrastructure/CacheConstants.java b/src/main/java/com/monkeyk/sos/infrastructure/CacheConstants.java
index 3fe0f37..59b0f89 100644
--- a/src/main/java/com/monkeyk/sos/infrastructure/CacheConstants.java
+++ b/src/main/java/com/monkeyk/sos/infrastructure/CacheConstants.java
@@ -9,35 +9,32 @@ package com.monkeyk.sos.infrastructure;
  *
  * @author Shengzhao Li
  */
-public abstract class CacheConstants {
+public interface CacheConstants {
 
     /**
      * client Details Cache, key is clientId
      */
-    public static final String CLIENT_DETAILS_CACHE = "clientDetailsCache";
+    String CLIENT_DETAILS_CACHE = "clientDetailsCache";
 
     /**
      * access Token Cache, key is token
      */
-    public static final String ACCESS_TOKEN_CACHE = "accessTokenCache";
+    String ACCESS_TOKEN_CACHE = "accessTokenCache";
 
     /**
      * refresh Token Cache, key is token
      */
-    public static final String REFRESH_TOKEN_CACHE = "refreshTokenCache";
+    String REFRESH_TOKEN_CACHE = "refreshTokenCache";
 
     /**
      * authorization Code Cache, key is code
      */
-    public static final String AUTHORIZATION_CODE_CACHE = "authorizationCodeCache";
+    String AUTHORIZATION_CODE_CACHE = "authorizationCodeCache";
 
     /**
      * user Cache, key is username
      */
-    public static final String USER_CACHE = "userCache";
+    String USER_CACHE = "userCache";
 
 
-    private CacheConstants() {
-    }
-
 }
diff --git a/src/main/java/com/monkeyk/sos/infrastructure/SOSCacheUtils.java b/src/main/java/com/monkeyk/sos/infrastructure/SOSCacheUtils.java
new file mode 100644
index 0000000..27073b1
--- /dev/null
+++ b/src/main/java/com/monkeyk/sos/infrastructure/SOSCacheUtils.java
@@ -0,0 +1,41 @@
+package com.monkeyk.sos.infrastructure;
+
+import com.monkeyk.sos.web.context.BeanProvider;
+import org.springframework.cache.Cache;
+import org.springframework.cache.CacheManager;
+import org.springframework.util.Assert;
+
+/**
+ * 2018/10/14
+ * <p>
+ * <p>
+ * Cache 操作相关
+ *
+ * @author Shengzhao Li
+ * @since 1.0
+ */
+public class SOSCacheUtils implements CacheConstants {
+
+
+    private SOSCacheUtils() {
+    }
+
+
+    /**
+     * 用户 Cache
+     *
+     * @return Cache instance
+     */
+    public static Cache userCache() {
+        final CacheManager cacheManager = getCacheManager();
+        return cacheManager.getCache(USER_CACHE);
+    }
+
+    private static CacheManager getCacheManager() {
+        final CacheManager cacheManager = BeanProvider.getBean(CacheManager.class);
+        Assert.notNull(cacheManager, "cacheManager is null");
+        return cacheManager;
+    }
+
+
+}
diff --git a/src/main/java/com/monkeyk/sos/service/business/CurrentUserJsonDtoLoader.java b/src/main/java/com/monkeyk/sos/service/business/CurrentUserJsonDtoLoader.java
new file mode 100644
index 0000000..d7c6706
--- /dev/null
+++ b/src/main/java/com/monkeyk/sos/service/business/CurrentUserJsonDtoLoader.java
@@ -0,0 +1,40 @@
+package com.monkeyk.sos.service.business;
+
+import com.monkeyk.sos.domain.dto.UserJsonDto;
+import com.monkeyk.sos.domain.shared.security.WdcyUserDetails;
+import com.monkeyk.sos.domain.user.UserRepository;
+import com.monkeyk.sos.web.context.BeanProvider;
+import org.springframework.security.core.Authentication;
+import org.springframework.security.core.context.SecurityContextHolder;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+
+/**
+ * 2018/10/14
+ *
+ * @author Shengzhao Li
+ * @since 1.0
+ */
+public class CurrentUserJsonDtoLoader {
+
+
+    private transient UserRepository userRepository = BeanProvider.getBean(UserRepository.class);
+
+    public CurrentUserJsonDtoLoader() {
+    }
+
+    public UserJsonDto load() {
+
+        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
+        final Object principal = authentication.getPrincipal();
+
+        if (authentication instanceof OAuth2Authentication &&
+                (principal instanceof String || principal instanceof org.springframework.security.core.userdetails.User)) {
+            OauthUserJsonDtoLoader jsonDtoLoader = new OauthUserJsonDtoLoader((OAuth2Authentication) authentication);
+            return jsonDtoLoader.load();
+        } else {
+            final WdcyUserDetails userDetails = (WdcyUserDetails) principal;
+            return new UserJsonDto(userRepository.findByGuid(userDetails.user().guid()));
+        }
+    }
+
+}
diff --git a/src/main/java/com/monkeyk/sos/service/business/OauthUserJsonDtoLoader.java b/src/main/java/com/monkeyk/sos/service/business/OauthUserJsonDtoLoader.java
new file mode 100644
index 0000000..8acf119
--- /dev/null
+++ b/src/main/java/com/monkeyk/sos/service/business/OauthUserJsonDtoLoader.java
@@ -0,0 +1,35 @@
+package com.monkeyk.sos.service.business;
+
+import com.monkeyk.sos.domain.dto.UserJsonDto;
+import org.springframework.security.core.GrantedAuthority;
+import org.springframework.security.oauth2.provider.OAuth2Authentication;
+
+import java.util.Collection;
+
+/**
+ * 2018/10/14
+ *
+ * @author Shengzhao Li
+ * @since 1.0
+ */
+public class OauthUserJsonDtoLoader {
+
+    private OAuth2Authentication oAuth2Authentication;
+
+    public OauthUserJsonDtoLoader(OAuth2Authentication oAuth2Authentication) {
+        this.oAuth2Authentication = oAuth2Authentication;
+    }
+
+    public UserJsonDto load() {
+
+        UserJsonDto userJsonDto = new UserJsonDto();
+        userJsonDto.setUsername(oAuth2Authentication.getName());
+
+        final Collection<GrantedAuthority> authorities = oAuth2Authentication.getAuthorities();
+        for (GrantedAuthority authority : authorities) {
+            userJsonDto.getPrivileges().add(authority.getAuthority());
+        }
+
+        return userJsonDto;
+    }
+}
diff --git a/src/main/java/com/monkeyk/sos/service/business/UserFormSaver.java b/src/main/java/com/monkeyk/sos/service/business/UserFormSaver.java
new file mode 100644
index 0000000..d185b02
--- /dev/null
+++ b/src/main/java/com/monkeyk/sos/service/business/UserFormSaver.java
@@ -0,0 +1,43 @@
+package com.monkeyk.sos.service.business;
+
+import com.monkeyk.sos.domain.dto.UserFormDto;
+import com.monkeyk.sos.domain.user.User;
+import com.monkeyk.sos.domain.user.UserRepository;
+import com.monkeyk.sos.infrastructure.SOSCacheUtils;
+import com.monkeyk.sos.web.WebUtils;
+import com.monkeyk.sos.web.context.BeanProvider;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * 2018/10/14
+ *
+ * @author Shengzhao Li
+ * @since 1.0
+ */
+public class UserFormSaver {
+
+
+    private static final Logger LOG = LoggerFactory.getLogger(UserFormSaver.class);
+
+    private transient UserRepository userRepository = BeanProvider.getBean(UserRepository.class);
+
+
+    private UserFormDto formDto;
+
+    public UserFormSaver(UserFormDto formDto) {
+        this.formDto = formDto;
+    }
+
+    public String save() {
+
+        User user = formDto.newUser();
+        userRepository.saveUser(user);
+        LOG.debug("{}|Save User: {}", WebUtils.getIp(), user);
+
+        //Add to cache
+        SOSCacheUtils.userCache().put(user.username(), user);
+
+        return user.guid();
+    }
+}
diff --git a/src/main/java/com/monkeyk/sos/service/impl/UserServiceImpl.java b/src/main/java/com/monkeyk/sos/service/impl/UserServiceImpl.java
index f7aabe6..78f0797 100644
--- a/src/main/java/com/monkeyk/sos/service/impl/UserServiceImpl.java
+++ b/src/main/java/com/monkeyk/sos/service/impl/UserServiceImpl.java
@@ -8,16 +8,13 @@ import com.monkeyk.sos.domain.shared.security.WdcyUserDetails;
 import com.monkeyk.sos.domain.user.User;
 import com.monkeyk.sos.domain.user.UserRepository;
 import com.monkeyk.sos.service.UserService;
+import com.monkeyk.sos.service.business.CurrentUserJsonDtoLoader;
+import com.monkeyk.sos.service.business.UserFormSaver;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.security.core.Authentication;
-import org.springframework.security.core.GrantedAuthority;
-import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.userdetails.UserDetails;
 import org.springframework.security.core.userdetails.UsernameNotFoundException;
-import org.springframework.security.oauth2.provider.OAuth2Authentication;
 import org.springframework.stereotype.Service;
 
-import java.util.Collection;
 import java.util.List;
 
 /**
@@ -43,16 +40,8 @@ public class UserServiceImpl implements UserService {
 
     @Override
     public UserJsonDto loadCurrentUserJsonDto() {
-        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
-        final Object principal = authentication.getPrincipal();
-
-        if (authentication instanceof OAuth2Authentication &&
-                (principal instanceof String || principal instanceof org.springframework.security.core.userdetails.User)) {
-            return loadOauthUserJsonDto((OAuth2Authentication) authentication);
-        } else {
-            final WdcyUserDetails userDetails = (WdcyUserDetails) principal;
-            return new UserJsonDto(userRepository.findByGuid(userDetails.user().guid()));
-        }
+        CurrentUserJsonDtoLoader dtoLoader = new CurrentUserJsonDtoLoader();
+        return dtoLoader.load();
     }
 
     @Override
@@ -70,21 +59,9 @@ public class UserServiceImpl implements UserService {
 
     @Override
     public String saveUser(UserFormDto formDto) {
-        User user = formDto.newUser();
-        userRepository.saveUser(user);
-        return user.guid();
+        UserFormSaver saver = new UserFormSaver(formDto);
+        return saver.save();
     }
 
 
-    private UserJsonDto loadOauthUserJsonDto(OAuth2Authentication oAuth2Authentication) {
-        UserJsonDto userJsonDto = new UserJsonDto();
-        userJsonDto.setUsername(oAuth2Authentication.getName());
-
-        final Collection<GrantedAuthority> authorities = oAuth2Authentication.getAuthorities();
-        for (GrantedAuthority authority : authorities) {
-            userJsonDto.getPrivileges().add(authority.getAuthority());
-        }
-
-        return userJsonDto;
-    }
 }
\ No newline at end of file
diff --git a/src/main/java/com/monkeyk/sos/web/context/BeanProvider.java b/src/main/java/com/monkeyk/sos/web/context/BeanProvider.java
new file mode 100644
index 0000000..ae3d845
--- /dev/null
+++ b/src/main/java/com/monkeyk/sos/web/context/BeanProvider.java
@@ -0,0 +1,39 @@
+package com.monkeyk.sos.web.context;
+
+import org.springframework.context.ApplicationContext;
+
+/**
+ * 2018/10/14
+ * <p>
+ * Spring bean容器, 启动时初始化
+ *
+ * @author Shengzhao Li
+ * @see SOSContextLoaderListener
+ * @since 1.0
+ */
+public abstract class BeanProvider {
+
+    private static ApplicationContext springApplicationContext;
+
+
+    //private
+    private BeanProvider() {
+    }
+
+    static void initialize(ApplicationContext applicationContext) {
+        BeanProvider.springApplicationContext = applicationContext;
+    }
+
+    public static <T> T getBean(Class<T> clazz) {
+        return springApplicationContext == null ? null : springApplicationContext.getBean(clazz);
+    }
+
+    @SuppressWarnings("unchecked")
+    public static <T> T getBean(String beanId) {
+        if (springApplicationContext == null) {
+            return null;
+        }
+        return (T) springApplicationContext.getBean(beanId);
+    }
+
+}
diff --git a/src/main/java/com/monkeyk/sos/web/context/SOSContextLoaderListener.java b/src/main/java/com/monkeyk/sos/web/context/SOSContextLoaderListener.java
new file mode 100644
index 0000000..f612289
--- /dev/null
+++ b/src/main/java/com/monkeyk/sos/web/context/SOSContextLoaderListener.java
@@ -0,0 +1,28 @@
+package com.monkeyk.sos.web.context;
+
+import org.springframework.web.context.ContextLoaderListener;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.WebApplicationContextUtils;
+
+import javax.servlet.ServletContextEvent;
+
+/**
+ * 2018/10/14
+ * <p>
+ * <p>
+ * 扩展 Spring Context, 方便获取 bean
+ *
+ * @author Shengzhao Li
+ * @since 1.0
+ */
+public class SOSContextLoaderListener extends ContextLoaderListener {
+
+
+    @Override
+    public void contextInitialized(ServletContextEvent event) {
+        super.contextInitialized(event);
+        //ext
+        WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(event.getServletContext());
+        BeanProvider.initialize(applicationContext);
+    }
+}
diff --git a/src/main/java/com/monkeyk/sos/web/controller/OAuthRestController.java b/src/main/java/com/monkeyk/sos/web/controller/OAuthRestController.java
index 7c52f4a..e893c9b 100644
--- a/src/main/java/com/monkeyk/sos/web/controller/OAuthRestController.java
+++ b/src/main/java/com/monkeyk/sos/web/controller/OAuthRestController.java
@@ -137,6 +137,16 @@ public class OAuthRestController implements InitializingBean, ApplicationContext
         String clientId = getClientId(parameters);
         ClientDetails authenticatedClient = clientDetailsService.loadClientByClientId(clientId);
 
+        //validate client_secret
+        String clientSecret = getClientSecret(parameters);
+        if (clientSecret == null || clientSecret.equals("")) {
+            throw new InvalidClientException("Bad client credentials");
+        } else {
+            if (!clientSecret.equals(authenticatedClient.getClientSecret())) {
+                throw new InvalidClientException("Bad client credentials");
+            }
+        }
+
         TokenRequest tokenRequest = oAuth2RequestFactory.createTokenRequest(parameters, authenticatedClient);
 
         if (clientId != null && !"".equals(clientId)) {
@@ -149,9 +159,7 @@ public class OAuthRestController implements InitializingBean, ApplicationContext
             }
         }
 
-        if (authenticatedClient != null) {
-            oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);
-        }
+        oAuth2RequestValidator.validateScope(tokenRequest, authenticatedClient);
 
         final String grantType = tokenRequest.getGrantType();
         if (!StringUtils.hasText(grantType)) {
@@ -227,7 +235,7 @@ public class OAuthRestController implements InitializingBean, ApplicationContext
      *
      * @param e Exception
      * @return ResponseEntity
-     * @throws Exception
+     * @throws Exception Exception
      * @see org.springframework.security.oauth2.provider.endpoint.CheckTokenEndpoint#handleException(Exception)
      */
     @ExceptionHandler(InvalidTokenException.class)
@@ -238,18 +246,23 @@ public class OAuthRestController implements InitializingBean, ApplicationContext
 
 
     private boolean isRefreshTokenRequest(Map<String, String> parameters) {
-        return "refresh_token".equals(parameters.get("grant_type")) && parameters.get("refresh_token") != null;
+        return "refresh_token".equals(parameters.get(OAuth2Utils.GRANT_TYPE)) && parameters.get("refresh_token") != null;
     }
 
     private boolean isAuthCodeRequest(Map<String, String> parameters) {
-        return "authorization_code".equals(parameters.get("grant_type")) && parameters.get("code") != null;
+        return "authorization_code".equals(parameters.get(OAuth2Utils.GRANT_TYPE)) && parameters.get("code") != null;
     }
 
 
     protected String getClientId(Map<String, String> parameters) {
-        return parameters.get("client_id");
+        return parameters.get(OAuth2Utils.CLIENT_ID);
     }
 
+    protected String getClientSecret(Map<String, String> parameters) {
+        return parameters.get("client_secret");
+    }
+
+
     private AuthenticationManager getAuthenticationManager() {
         return this.authenticationManager;
     }
diff --git a/src/main/webapp/WEB-INF/web.xml b/src/main/webapp/WEB-INF/web.xml
index 220efb5..81351d7 100644
--- a/src/main/webapp/WEB-INF/web.xml
+++ b/src/main/webapp/WEB-INF/web.xml
@@ -132,11 +132,11 @@
     </listener>
 
     <!--
-        Spring Context 监听
+        Spring Context 监听, 扩展实现l
     -->
     <!-- Spring context listener -->
     <listener>
-        <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
+        <listener-class>com.monkeyk.sos.web.context.SOSContextLoaderListener</listener-class>
     </listener>
 
 
diff --git a/src/main/webapp/index.jsp b/src/main/webapp/index.jsp
index 41ba345..a2ddf86 100644
--- a/src/main/webapp/index.jsp
+++ b/src/main/webapp/index.jsp
@@ -5,6 +5,7 @@
 
 <%@ page contentType="text/html;charset=UTF-8" language="java" trimDirectiveWhitespaces="true" %>
 <%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
+<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
 <!DOCTYPE HTML>
 <html>
 <head>
@@ -17,11 +18,20 @@
     <small class="badge" title="Version">1.0</small>
 </h2>
 
-<p>
-    <a href="${contextPath}/login.jsp">Login</a>
-    &nbsp;|&nbsp;
-    <a href="${contextPath}/logout.do">Logout</a>
-</p>
+<c:if test="${not empty SPRING_SECURITY_CONTEXT.authentication.principal.username}" var="logged">
+    Logged: <sec:authentication property="principal.username"/>
+    <p>
+        <a href="${contextPath}/logout.do">Logout</a>
+    </p>
+</c:if>
+<c:if test="${not logged}">
+    <p>
+        <a href="${contextPath}/login.jsp">Login</a>
+        &nbsp;|&nbsp;
+        <a href="${contextPath}/logout.do">Logout</a>
+    </p>
+</c:if>
+
 
 <div>
     操作说明: