Bläddra i källkod

Merge branch 'dev' into manage-console

huxz 8 år sedan
förälder
incheckning
0e37e5e5ed
51 ändrade filer med 3414 tillägg och 85 borttagningar
  1. 8 0
      pom.xml
  2. 29 7
      sso-server/pom.xml
  3. 81 0
      sso-server/src/main/java/com/uas/sso/SSOConfiguration.java
  4. 98 0
      sso-server/src/main/java/com/uas/sso/controller/AppealController.java
  5. 71 5
      sso-server/src/main/java/com/uas/sso/controller/BaseController.java
  6. 288 0
      sso-server/src/main/java/com/uas/sso/controller/ChangeAdminController.java
  7. 139 50
      sso-server/src/main/java/com/uas/sso/controller/LoginController.java
  8. 9 4
      sso-server/src/main/java/com/uas/sso/controller/PersonalRegisterController.java
  9. 366 0
      sso-server/src/main/java/com/uas/sso/controller/ResetPasswordController.java
  10. 329 0
      sso-server/src/main/java/com/uas/sso/controller/UpdateUserController.java
  11. 28 5
      sso-server/src/main/java/com/uas/sso/controller/UserManagerController.java
  12. 29 3
      sso-server/src/main/java/com/uas/sso/controller/UserspaceManageController.java
  13. 1 1
      sso-server/src/main/java/com/uas/sso/controller/UserspaceRegisterController.java
  14. 116 0
      sso-server/src/main/java/com/uas/sso/controller/ValidController.java
  15. 13 0
      sso-server/src/main/java/com/uas/sso/dao/ChangeAdminDao.java
  16. 13 0
      sso-server/src/main/java/com/uas/sso/dao/ResetPwdAppealDao.java
  17. 20 0
      sso-server/src/main/java/com/uas/sso/dao/UserDao.java
  18. 21 0
      sso-server/src/main/java/com/uas/sso/dao/UserRecordDao.java
  19. 177 0
      sso-server/src/main/java/com/uas/sso/entity/ChangeAdmin.java
  20. 149 0
      sso-server/src/main/java/com/uas/sso/entity/ResetPwdAppeal.java
  21. 18 0
      sso-server/src/main/java/com/uas/sso/entity/Token.java
  22. 33 2
      sso-server/src/main/java/com/uas/sso/entity/User.java
  23. 91 0
      sso-server/src/main/java/com/uas/sso/entity/UserQuestion.java
  24. 56 0
      sso-server/src/main/java/com/uas/sso/entity/UserRecord.java
  25. 19 2
      sso-server/src/main/java/com/uas/sso/entity/Userspace.java
  26. 58 0
      sso-server/src/main/java/com/uas/sso/filter/SSOInterceptor.java
  27. 11 0
      sso-server/src/main/java/com/uas/sso/profile/Dev.java
  28. 7 0
      sso-server/src/main/java/com/uas/sso/profile/Prod.java
  29. 7 0
      sso-server/src/main/java/com/uas/sso/profile/Test.java
  30. 17 0
      sso-server/src/main/java/com/uas/sso/service/ChangeAdminService.java
  31. 17 0
      sso-server/src/main/java/com/uas/sso/service/ResetPwdAppealService.java
  32. 86 4
      sso-server/src/main/java/com/uas/sso/service/UserService.java
  33. 37 0
      sso-server/src/main/java/com/uas/sso/service/UserspaceService.java
  34. 20 0
      sso-server/src/main/java/com/uas/sso/service/UserspaceValidService.java
  35. 35 0
      sso-server/src/main/java/com/uas/sso/service/impl/ChangeAdminServiceImpl.java
  36. 30 0
      sso-server/src/main/java/com/uas/sso/service/impl/ResetPwdAppealServiceImpl.java
  37. 1 1
      sso-server/src/main/java/com/uas/sso/service/impl/UserAccountService.java
  38. 1 1
      sso-server/src/main/java/com/uas/sso/service/impl/UserAccountServiceImpl.java
  39. 147 0
      sso-server/src/main/java/com/uas/sso/service/impl/UserServiceImpl.java
  40. 54 0
      sso-server/src/main/java/com/uas/sso/service/impl/UserspaceServiceImpl.java
  41. 19 0
      sso-server/src/main/java/com/uas/sso/service/impl/UserspaceValidServiceImpl.java
  42. 28 0
      sso-server/src/main/java/com/uas/sso/support/SystemSession.java
  43. 29 0
      sso-server/src/main/java/com/uas/sso/timertask/UserLockTimerTask.java
  44. 105 0
      sso-server/src/main/java/com/uas/sso/util/CaptchaUtil.java
  45. 93 0
      sso-server/src/main/java/com/uas/sso/util/FastjsonUtils.java
  46. 35 0
      sso-server/src/main/java/com/uas/sso/util/FileUrl.java
  47. 306 0
      sso-server/src/main/java/com/uas/sso/util/HttpUtils.java
  48. 33 0
      sso-server/src/main/java/com/uas/sso/util/ParameterUtils.java
  49. 12 0
      sso-server/src/main/resources/dev/account.properties
  50. 12 0
      sso-server/src/main/resources/prod/account.properties
  51. 12 0
      sso-server/src/main/resources/test/account.properties

+ 8 - 0
pom.xml

@@ -31,6 +31,7 @@
         <zkclient.version>0.1</zkclient.version>
         <dfs.version>0.0.2</dfs.version>
 
+        <upload.version>1.3.2</upload.version>
         <pinyin.version>2.5.1</pinyin.version>
     </properties>
 
@@ -93,6 +94,13 @@
                 <version>${dfs.version}</version>
             </dependency>
 
+            <!-- fileupload -->
+            <dependency>
+                <groupId>commons-fileupload</groupId>
+                <artifactId>commons-fileupload</artifactId>
+                <version>${upload.version}</version>
+            </dependency>
+
             <dependency>
                 <groupId>com.belerweb</groupId>
                 <artifactId>pinyin4j</artifactId>

+ 29 - 7
sso-server/pom.xml

@@ -119,6 +119,25 @@
 			<groupId>com.belerweb</groupId>
 			<artifactId>pinyin4j</artifactId>
 		</dependency>
+        <dependency>
+            <groupId>commons-fileupload</groupId>
+            <artifactId>commons-fileupload</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpmime</artifactId>
+            <version>4.4</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpcore</artifactId>
+            <version>4.4.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.httpcomponents</groupId>
+            <artifactId>httpclient</artifactId>
+            <version>4.4</version>
+        </dependency>
 	</dependencies>
 
 	<build>
@@ -144,13 +163,16 @@
 				</configuration>
 			</plugin>
 			<plugin>
-				<groupId>org.apache.maven.plugins</groupId>
-				<artifactId>maven-compiler-plugin</artifactId>
-				<configuration>
-					<encoding>${project.build.sourceEncoding}</encoding>
-					<source>1.7</source>
-					<target>1.7</target>
-				</configuration>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-compiler-plugin</artifactId>
+                <configuration>
+                    <source>1.7</source>
+                    <target>1.7</target>
+                    <compilerArguments>
+                        <verbose />
+                        <bootclasspath>${java.home}\lib\rt.jar;${java.home}\lib\jce.jar</bootclasspath>
+                    </compilerArguments>
+                </configuration>
 			</plugin>
 			<plugin>
 				<artifactId>maven-resources-plugin</artifactId>

+ 81 - 0
sso-server/src/main/java/com/uas/sso/SSOConfiguration.java

@@ -0,0 +1,81 @@
+package com.uas.sso;
+
+import com.uas.sso.profile.Test;
+import com.uas.sso.web.AccountConfigurer;
+import com.uas.sso.filter.SSOInterceptor;
+import com.uas.sso.profile.Dev;
+import com.uas.sso.profile.Prod;
+import com.uas.sso.util.ContextUtils;
+import org.apache.log4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
+
+import java.util.Properties;
+
+
+/**
+ * SSOconfig 配置
+ *
+ * @author hejq
+ */
+@Configuration
+public class SSOConfiguration extends WebMvcConfigurerAdapter {
+
+    @Autowired
+    private SSOInterceptor ssoInterceptor;
+
+    private Logger logger = Logger.getLogger(this.getClass());
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+
+        /**
+         * SSO过滤, 这个地方拦截配置
+         */
+        registry.addInterceptor(ssoInterceptor).addPathPatterns("/**").
+                excludePathPatterns("/sso/*/register/**", "/sso/login/**", "/api/user/**", "/api/userspace/**");
+
+    }
+
+    @Bean
+    @Dev
+    public AccountConfigurer devAccountConfigurer() {
+        return accountConfigurer("dev");
+    }
+
+    @Bean
+    @Test
+    public AccountConfigurer testAccountConfigurer() {
+        return accountConfigurer("test");
+    }
+
+    @Bean
+    @Prod
+    public AccountConfigurer prodAccountConfigurer() {
+        return accountConfigurer("prod");
+    }
+
+    /**
+     * 获取当前环境下的配置
+     *
+     * @param profile
+     * @return
+     */
+    private AccountConfigurer accountConfigurer(String profile) {
+        AccountConfigurer accountConfigurer = new AccountConfigurer();
+        accountConfigurer.setApplicationContext(ContextUtils.getApplicationContext());
+        Properties properties = new Properties();
+        String configPath = profile + "/account.properties";
+        logger.info("***: " + configPath);
+        try {
+            properties.load(this.getClass().getClassLoader().getResourceAsStream(configPath));
+        } catch (Throwable e) {
+            throw new IllegalStateException("配置加载失败" + configPath);
+        }
+        accountConfigurer.initProperties(properties);
+        return accountConfigurer;
+    }
+}

+ 98 - 0
sso-server/src/main/java/com/uas/sso/controller/AppealController.java

@@ -0,0 +1,98 @@
+package com.uas.sso.controller;
+
+import com.uas.sso.entity.ResetPwdAppeal;
+import com.uas.sso.entity.Token;
+import com.uas.sso.service.ResetPwdAppealService;
+import com.uas.sso.service.UserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.validation.Valid;
+
+import static com.sun.xml.internal.ws.api.message.Packet.Status.Request;
+
+/**
+ * @author wangmh
+ * @create 2018-01-16 8:50
+ * @desc 申述controller
+ **/
+@RestController
+@RequestMapping("/appeal")
+public class AppealController extends BaseController {
+
+    @Autowired
+    private UserService userService;
+
+    @Autowired
+    private ResetPwdAppealService resetPwdAppealService;
+
+    /**
+     * 获取手机号验证码
+     *
+     * @author wangmh
+     * @date 2018/1/16 10:37
+     * @param mobile 手机号
+     * @return 验证码tokenId
+     */
+    @RequestMapping(value = "/check/mobile", method = RequestMethod.GET)
+    public ModelMap checkMobile(String mobile) {
+        if (!userService.mobileHasRegistered(mobile)) {
+            return error("用户手机号未被注册");
+        }
+
+        String token = getMobileCode(mobile);
+        return success(new ModelMap("token", token));
+    }
+
+    /**
+     * 校验验证码
+     *
+     * @author wangmh
+     * @date 2018/1/16 10:44
+     * @param mobile 手机号
+     * @param token 验证码tokenId
+     * @param code 验证码
+     * @return
+     */
+    @RequestMapping(value = "/checkMobile", method = RequestMethod.POST)
+    public ModelMap checkMobile(String mobile, @RequestParam String token, String code) {
+        Token existToken = tokenService.findOne(token);
+        if (existToken == null || existToken.isExpired()) {
+            return error("验证码已过期,请重新获取");
+        }
+
+        // 校验验证码
+        checkMobileCode(token, mobile, code);
+
+        // 返回信息
+        return success();
+    }
+
+    /**
+     * 找回密码申述
+     * @param resetPwdAppeal 申述信息
+     * @param token 验证码tokenId
+     * @param code 验证码
+     * @return
+     */
+    @RequestMapping(value = "/resetPwd", method = RequestMethod.POST)
+    public ModelMap resetPwd(@Valid ResetPwdAppeal resetPwdAppeal, String token, String code) {
+        Token existToken = tokenService.findOne(token);
+        if (existToken == null || existToken.isExpired()) {
+            return error("验证码已过期,请重新获取");
+        }
+
+        // TODO 参数空检验
+
+        // 校验验证码
+        checkMobileCode(token, resetPwdAppeal.getMobile(), code);
+
+        // 保存申述信息
+        resetPwdAppealService.submit(resetPwdAppeal);
+        return success();
+    }
+}

+ 71 - 5
sso-server/src/main/java/com/uas/sso/controller/BaseController.java

@@ -1,6 +1,7 @@
 package com.uas.sso.controller;
 
 import com.alibaba.fastjson.JSON;
+import com.uas.message.mail.service.MailService;
 import com.uas.message.sms.service.SmsService;
 import com.uas.sso.core.Const;
 import com.uas.sso.core.PasswordStrength;
@@ -44,6 +45,9 @@ public class BaseController {
     @Autowired
     protected SmsService smsService;
 
+    @Autowired
+    protected MailService mailService;
+
     @Autowired
     protected SettingService settingService;
 
@@ -142,17 +146,21 @@ public class BaseController {
     }
 
     /**
-     * 获取手机号验证码
+     * 获取验证码
      *
+     * @param mobile 手机号
+     * @param email 邮箱
      * @return tokenId
      */
-    protected String getMobileCode(String mobile) {
+    protected String getValidCode(String mobile, String email) {
         // 随机获得验证码
         String code = StringUtil.getRandomNumber(6);
         Token token = new Token(code, 10 * 60);
+        System.out.println(code);
 
         // 设置绑定手机,防止获取验证码之后修改手机号
         token.setMobile(mobile);
+        token.setEmail(email);
 
         // 将token存到Redis服务器上
         tokenService.save(token);
@@ -172,21 +180,54 @@ public class BaseController {
             e.printStackTrace();
         }
 
+        // 邮件
+        try {
+            if (!StringUtils.isEmpty(email)) {
+                Setting mailTplId = settingService.findOne("templateForSendEmailWhenRegister");
+                if (!StringUtils.isEmpty(mailTplId)) {
+                    mailService.send(mailTplId.getValue(), email, data);
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
         // 返回tokenId
         return token.getId();
     }
 
     /**
-     * 校验手机号
+     * 获取手机号验证码
+     *
+     * @param mobile 手机号
+     * @return tokenId
+     */
+    protected String getMobileCode(String mobile) {
+        return getValidCode(mobile, null);
+    }
+
+    /**
+     * 获取邮箱验证码
+     *
+     * @param email 邮箱
+     * @return
+     */
+    protected String getEmailCode(String email) {
+        return getValidCode(null, email);
+    }
+
+    /**
+     * 校验验证码
      *
      * @param token  验证码tokenID
      * @param mobile 手机号
+     * @param email 邮箱
      * @param code   验证码
      * @return
      * @throws VisibleError 校验失败则抛异常
      *                      当参数异常,token过期或者token绑定的手机号不对时抛出此异常
      */
-    protected void checkMobileCode(String token, String mobile, String code) {
+    protected void checkValidCode(String token, String mobile, String email, String code) {
         // 校验参数
         if (StringUtils.isEmpty(token) || StringUtils.isEmpty(code)) {
             throw new VisibleError("参数错误");
@@ -195,7 +236,10 @@ public class BaseController {
         if (existToken == null || existToken.isExpired()) {
             throw new VisibleError("验证码已经失效,请重新获取");
         }
-        if (StringUtils.isEmpty(mobile) || !mobile.equals(existToken.getMobile())) {
+        if (!StringUtils.isEmpty(existToken.getMobile()) && !existToken.getMobile().equals(mobile)) {
+            throw new VisibleError("手机号被修改,请重新获取验证码");
+        }
+        if (!StringUtils.isEmpty(existToken.getEmail()) && !existToken.getEmail().equals(email)) {
             throw new VisibleError("手机号被修改,请重新获取验证码");
         }
 
@@ -206,6 +250,28 @@ public class BaseController {
         }
     }
 
+    /**
+     * 校验手机号验证码
+     *
+     * @param token  验证码tokenID
+     * @param mobile 手机号
+     * @param code   验证码
+     */
+    protected void checkMobileCode(String token, String mobile, String code) {
+        checkValidCode(token, mobile, null, code);
+    }
+
+    /**
+     * 校验手机号验证码
+     *
+     * @param token  验证码tokenID
+     * @param email 邮箱
+     * @param code   验证码
+     */
+    protected void checkEmailCode(String token, String email, String code) {
+        checkValidCode(token, null, email, code);
+    }
+
     /**
      * 校验手机号格式
      *

+ 288 - 0
sso-server/src/main/java/com/uas/sso/controller/ChangeAdminController.java

@@ -0,0 +1,288 @@
+package com.uas.sso.controller;
+
+import com.uas.sso.core.Status;
+import com.uas.sso.entity.*;
+import com.uas.sso.service.ChangeAdminService;
+import com.uas.sso.service.UserService;
+import com.uas.sso.service.UserspaceService;
+import com.uas.sso.support.SystemSession;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.ui.ModelMap;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author wangmh
+ * @create 2018-01-15 10:24
+ * @desc 更换管理员controller(需要登录)
+ **/
+@RestController
+@RequestMapping("/sso/change/admin")
+public class ChangeAdminController extends BaseController {
+
+    @Autowired
+    private UserService userService;
+
+    @Autowired
+    private UserspaceService userspaceService;
+
+    @Autowired
+    private ChangeAdminService changeAdminService;
+
+    @Autowired
+    private static final String STEP_SECONT_TOKEN = "changeAdmin";
+
+    /**
+     * 获取校验类型
+     *
+     * @return
+     */
+    @RequestMapping(value = "/checkType", method = RequestMethod.GET)
+    public ModelMap getCheckType() {
+        // 获取用户信息
+        UserAccount userAccount = SystemSession.getUserAccount();
+        User user = userService.findOne(userAccount.getUserUU());
+
+        // 判断是否未企业管理员
+        Userspace userspace = userspaceService.findOne(userAccount.getSpaceUU());
+        if (!userspace.getAdminUU().equals(user.getUserUU())) {
+            return success();
+        }
+
+        // 设置返回数据
+        ModelMap data = new ModelMap();
+        data.put("mobile", Status.AUTHENTICATED.getCode() == user.getMobileValidCode() ? user.getMobile() : null);
+        data.put("email", Status.AUTHENTICATED.getCode() == user.getEmailValidCode() ? user.getEmail() : null);
+        data.put("questions", user.getQuestions());
+        request.getSession().setAttribute("user", user);
+        return success(data);
+    }
+
+    /**
+     * 手机号获取验证码
+     *
+     * @return
+     * @author wangmh
+     * @date 2018/1/15 11:52
+     */
+    @RequestMapping(value = "/check/mobile", method = RequestMethod.GET)
+    public ModelMap checkByMobile() {
+        UserAccount userAccount = SystemSession.getUserAccount();
+
+        // 获取验证码
+        String token = getMobileCode(userAccount.getMobile());
+
+        // 设置返回值
+        return success(new ModelMap("token", token));
+    }
+
+    /**
+     * 手机号校验验证码
+     *
+     * @return
+     * @author wangmh
+     * @date 2018/1/15 11:53
+     */
+    @RequestMapping(value = "/check/mobile", method = RequestMethod.POST)
+    public ModelMap checkByMobile(@RequestParam String token, @RequestParam String code) {
+        UserAccount userAccount = SystemSession.getUserAccount();
+
+        // 校验验证码
+        checkMobileCode(token, userAccount.getMobile(), code);
+        tokenService.delete(token);
+
+        // 设置返回值
+        Token existToken = new Token(userAccount, 7 * 24 * 60 * 60);
+        request.getSession().setAttribute("existToken", existToken);
+        tokenService.save(existToken);
+        return success(new ModelMap("token", existToken));
+    }
+
+    /**
+     * 获取邮箱验证
+     *
+     * @return
+     * @author wangmh
+     * @date 2018/1/15 13:56
+     */
+    @RequestMapping(value = "/check/email", method = RequestMethod.GET)
+    public ModelMap checkByEmail() {
+        UserAccount userAccount = SystemSession.getUserAccount();
+
+        // 设置发送邮件信息
+        Token existToken = new Token(userAccount, 7 * 24 * 60 * 60);
+        tokenService.save(existToken);
+        ModelMap data = new ModelMap();
+        data.put("vipName", userAccount.getVipName());
+        // TODO 邮件认证地址
+        data.put("url", "http://192.168.253.66:8081/sso/resetPwd/check/question?token="+existToken.getId());
+
+        // 发送邮件
+        String email = userAccount.getEmail();
+        if (!StringUtils.isEmpty(email)) {
+            Setting mailTplId = settingService.findOne("templateForSendMailWhenResetPassword");
+            if (!StringUtils.isEmpty(mailTplId)) {
+                mailService.send(mailTplId.getValue(), email, data);
+            }
+        }
+
+        // 设置返回值
+        request.getSession().setAttribute("existToken", existToken);
+        return success();
+    }
+
+    /**
+     * 获取用户的密保问题
+     *
+     * @author wangmh
+     * @date 2018/1/15 16:19
+     * @return
+     */
+    @RequestMapping(value = "/check/question", method = RequestMethod.GET)
+    public ModelMap checkByQuestion() {
+        UserAccount userAccount = SystemSession.getUserAccount();
+
+        // 查询密保
+        User user = userService.findOne(userAccount.getUserUU());
+        List<UserQuestion> questions = user.getQuestions();
+
+        // 将问题返回用户,答案放入session
+        Map<Long, String> userAnswer = new HashMap<>(questions.size());
+        for (UserQuestion question : questions) {
+            userAnswer.put(question.getId(), question.getAnswer());
+        }
+        request.getSession().setAttribute("answers", userAnswer);
+        ModelMap data = new ModelMap();
+        data.put("question", questions);
+        return success(data);
+    }
+
+    /**
+     * 校验用户密保答案
+     *
+     * @author wangmh
+     * @date 2018/1/15 16:20
+     * @param answers 用户输入的答案
+     * @return
+     */
+    @RequestMapping(value = "/check/question", method = RequestMethod.POST)
+    public ModelMap checkByQuestion(List<Map<String, Object>> answers) {
+        UserAccount userAccount = SystemSession.getUserAccount();
+
+        // 校验密保答案
+        Map<Long, String> userAnswer = (Map<Long, String>) request.getSession().getAttribute("answers");
+        for (Map<String, Object> answer : answers) {
+            if (!answer.get("answer").equals(userAnswer.get(answer.get("id")))){
+                return error("答案错误");
+            }
+        }
+
+        // 返回token
+        Token existToken = new Token(userAccount, 7 * 24 * 60 * 60);
+        request.getSession().setAttribute("existToken", existToken);
+        tokenService.save(existToken);
+        ModelMap data = new ModelMap();
+        data.put("token", existToken.getId());
+        return success(data);
+    }
+
+    /**
+     * 校验第一步传的token
+     * @param token 第一步返回的token
+     * @return
+     */
+    @RequestMapping(value = "/apply", method = RequestMethod.GET)
+    public ModelMap checkToken(@RequestParam String token) {
+        if (StringUtils.isEmpty(token)) {
+            return error("验证信息已过期,请重新验证");
+        }
+        Token existToken = tokenService.findOne(token);
+        if (existToken == null) {
+            return error("验证信息已过期,请重新验证");
+        }
+
+        return success();
+    }
+
+    /**
+     * 获取验证码
+     * 
+     * @author wangmh
+     * @date 2018/1/15 18:09
+     * @param mobile 新管理员手机号
+     * @param token 第一步返回的token
+     * @return
+     */
+    @RequestMapping(value = "/check/newMobile", method = RequestMethod.GET)
+    public ModelMap checkByNewMobile(String mobile, @RequestParam String token) {
+        
+        // 校验第一步返回的token
+        checkToken(token);
+
+        // 获取token并返回
+        return success(new ModelMap("token", getMobileCode(mobile)));
+    }
+
+    /**
+     * 校验验证码
+     *
+     * @author wangmh
+     * @date 2018/1/15 18:22
+     * @param mobile 手机号
+     * @param token 获取验证码返回的token
+     * @param code 验证码
+     * @return
+     */
+    @RequestMapping(value = "/check/newMobile", method = RequestMethod.POST)
+    public ModelMap checkByNewMobile(String mobile, @RequestParam String token, String code,
+                                     @RequestParam String codeToken, String changeReason, String contactTel) {
+
+        // 校验第一步返回的token
+        if (StringUtils.isEmpty(token)) {
+            return error("验证信息已过期,请重新验证");
+        }
+        Token existToken = tokenService.findOne(token);
+        if (existToken == null) {
+            return error("验证信息已过期,请重新验证");
+        }
+
+        // 校验空参数
+        if (StringUtils.isEmpty(changeReason.trim())) {
+            return error("更换原因不能为空");
+        }
+        if (StringUtils.isEmpty(contactTel.trim())) {
+            return error("联系电话不能为空");
+        }
+
+        // 校验验证码
+        checkMobileCode(codeToken, mobile, code);
+
+        // 获取新管理员
+        User afterAdmin = userService.findByMobile(mobile);
+
+        // 获取提交者
+        UserAccount userAccount = (UserAccount) existToken.getBind();
+
+        // 获取之前的管理员
+        Userspace userspace = userspaceService.findOne(userAccount.getSpaceUU());
+        User beforeAdmin = userService.findOne(userspace.getAdminUU());
+
+        ChangeAdmin changeAdmin = new ChangeAdmin();
+        changeAdmin.setSubmitterUU(userAccount.getUserUU());
+        changeAdmin.setBeforeAdminUU(beforeAdmin.getUserUU());
+        changeAdmin.setAfterAdminUU(afterAdmin.getUserUU());
+        changeAdmin.setChangeReason(changeReason);
+        changeAdmin.setContactTel(contactTel);
+        changeAdminService.submit(changeAdmin);
+
+        return success();
+    }
+
+}

+ 139 - 50
sso-server/src/main/java/com/uas/sso/controller/LoginController.java

@@ -8,11 +8,14 @@ import com.uas.sso.SSOToken;
 import com.uas.sso.common.util.HttpUtil;
 import com.uas.sso.core.Const;
 import com.uas.sso.entity.App;
+import com.uas.sso.entity.User;
 import com.uas.sso.entity.UserAccount;
+import com.uas.sso.entity.UserRecord;
 import com.uas.sso.service.AppService;
 import com.uas.sso.service.UserService;
 import com.uas.sso.service.impl.UserAccountService;
 import com.uas.sso.util.AccountTypeUtils;
+import com.uas.sso.util.CaptchaUtil;
 import com.uas.sso.web.waf.request.WafRequestWrapper;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.ui.ModelMap;
@@ -20,9 +23,10 @@ import org.springframework.util.CollectionUtils;
 import org.springframework.util.StringUtils;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
 import org.springframework.web.bind.annotation.RestController;
 
+import javax.servlet.ServletException;
+import java.io.IOException;
 import java.util.*;
 
 /**
@@ -35,6 +39,21 @@ import java.util.*;
 @RestController
 public class LoginController extends BaseController {
 
+    /**
+     * 密码输错3次
+     */
+    private static final int PWD_ERROR_FIVE_TIME = 5;
+
+    /**
+     * 密码输错3次
+     */
+    private static final int PWD_ERROR_THREE_TIME = 3;
+
+    /**
+     * 登录验证码存session的key值
+     */
+    private static final String LOGIN_CAPTCHA = "loginCaptcha";
+
     @Autowired
     private AppService appService;
 
@@ -45,7 +64,6 @@ public class LoginController extends BaseController {
     private UserAccountService userAccountService;
 
     @RequestMapping(method = RequestMethod.POST)
-    @ResponseBody
     public ModelMap login() {
         // 获取登录信息
         WafRequestWrapper wr = new WafRequestWrapper(request);
@@ -53,6 +71,7 @@ public class LoginController extends BaseController {
         String spaceUU = wr.getParameter("spaceUU");
         String username = StringUtils.trimAllWhitespace(wr.getParameter("username"));
         String password = wr.getParameter("password");
+        String captcha = wr.getParameter("captcha");
         String returnUrl = wr.getParameter("returnUrl");
         String baseUrl = wr.getParameter("baseUrl");
 
@@ -76,6 +95,34 @@ public class LoginController extends BaseController {
             return error("应用id不存在");
         }
 
+        // 获取用户基本信息
+        User user = userService.findByUsername(username);
+        if (user == null) {
+            return error("用户名或密码错误");
+        }
+
+        // 校验账户密码输错次数
+        int pwdErrorCount = user.getUserRecord() == null ? 0 : user.getUserRecord().getPwdErrorCount();
+        Object loginCaptcha = request.getSession().getAttribute(LOGIN_CAPTCHA);
+        String checkCode = loginCaptcha == null ? "" : loginCaptcha.toString();
+        if (pwdErrorCount >= PWD_ERROR_FIVE_TIME) {
+            return error("403", "密码错误次数已达上限,今日无法登陆");
+        }
+        // 校验账号是否被锁定,5次输错密码
+        if (pwdErrorCount >= PWD_ERROR_THREE_TIME && StringUtils.isEmpty(captcha)) {
+            return error("404", "验证码不能为空");
+        }
+        if (pwdErrorCount >= PWD_ERROR_THREE_TIME && !captcha.equalsIgnoreCase(checkCode)) {
+            return error("验证码错误");
+        }
+
+        // 校验密码
+        String encryPwd = userService.getEncryPassword(Const.ENCRY_FORMAT, password, user.getSalt());
+        if (!encryPwd.equals(user.getPassword())) {
+            pwdErrorCount = inputErrorPwd(user.getUserRecord());
+            return error("您输入的账号或密码有误").addAttribute("errorCount", pwdErrorCount);
+        }
+
         // 登录
         App controlApp = StringUtils.isEmpty(app.getUserControl()) ? app : appService.findOne(app.getUserControl());
         boolean personalEnable = Const.YES == controlApp.getPersonalEnable();
@@ -83,26 +130,16 @@ public class LoginController extends BaseController {
         if (StringUtils.isEmpty(spaceUU)) {
             /*企业uu号为空,让用户选择企业*/
             // 找到用户账号信息
-            List<UserAccount> userAccounts = getUserAccountByUserName(controlApp.getUid(), username);
+            List<UserAccount> userAccounts = userAccountService.findByUserUU(appId, user.getUserUU());
 
-            // 应用不允许个人账号,并且账号未绑定企业
-            if (!personalEnable && CollectionUtils.isEmpty(userAccounts)) {
-                return error("用户名或密码错误");
+            // 没有记录
+            if (CollectionUtils.isEmpty(userAccounts)) {
+                return error("您的账号为绑定企业并且当前应用不支持个人账号");
             }
 
             // 应用允许个人账号,并且账号未绑定企业,或者只绑定了一个企业,直接登录
             if (userAccounts.size() == 1) {
-                return loginByUser(userAccounts.get(0), password, returnUrl);
-            }
-
-            // 由于老账户存在多个账号绑定一个邮箱的情况,把密码不符合的企业去除
-            Iterator<UserAccount> iterator = userAccounts.iterator();
-            while (iterator.hasNext()) {
-                UserAccount userAccount = iterator.next();
-                String encryPwd = userService.getEncryPassword(Const.ENCRY_FORMAT, password, userAccount.getSalt());
-                if (!encryPwd.equals(userAccount.getPassword())) {
-                    iterator.remove();
-                }
+                return loginByUser(userAccounts.get(0), returnUrl, user.getUserRecord());
             }
 
             // 返回企业id和名称
@@ -110,14 +147,37 @@ public class LoginController extends BaseController {
         } else if (spaceUU.equals(Const.SPACEUU_PERSONAL)) {
             // 使用个人账号登录
             UserAccount userAccount = getUserAccountByUserName(controlApp.getUid(), username, null);
-            return loginByUser(userAccount, password, returnUrl);
+            return loginByUser(userAccount, returnUrl, user.getUserRecord());
         } else {
             // 带企业登录
             UserAccount userAccount = getUserAccountByUserName(controlApp.getUid(), username, spaceUU);
-            return loginByUser(userAccount, password, returnUrl);
+            return loginByUser(userAccount, returnUrl, user.getUserRecord());
         }
     }
 
+    /**
+     * 密码输错处理
+     *
+     * @param userRecord 用户登录记录
+     * @return
+     */
+    private int inputErrorPwd(UserRecord userRecord) {
+        // 密码输错次数+1
+        int pwdErrorCount = userRecord.getPwdErrorCount();
+        userRecord.setPwdErrorCount(++pwdErrorCount);
+        userService.save(userRecord);
+
+        // 设置返回值
+        return pwdErrorCount;
+    }
+
+    /**
+     * 根据用户名获得用户账号信息
+     *
+     * @param appId 应用
+     * @param username 用户名
+     * @return
+     */
     private List<UserAccount> getUserAccountByUserName(String appId, String username) {
         String type = AccountTypeUtils.getAccountType(username);
         if (AccountTypeUtils.MOBILE.equals(type)) {
@@ -130,13 +190,21 @@ public class LoginController extends BaseController {
         }
         if (AccountTypeUtils.UU_NUMBER.equals(type)) {
             // uu号登录
-            return userAccountService.findOneByUserUU(appId, Long.valueOf(username));
+            return userAccountService.findByUserUU(appId, Long.valueOf(username));
         }
 
         // 其余情况
         return null;
     }
 
+    /**
+     * 根据用户名和企业uu找到用户信息
+     *
+     * @param appId 应用
+     * @param username 用户名
+     * @param spaceUU 企业uu号
+     * @return
+     */
     private UserAccount getUserAccountByUserName(String appId, String username, String spaceUU) {
         String type = AccountTypeUtils.getAccountType(username);
         if (AccountTypeUtils.MOBILE.equals(type)) {
@@ -156,38 +224,37 @@ public class LoginController extends BaseController {
         return null;
     }
 
-    private ModelMap loginByUser(UserAccount userAccount, String password, String returnUrl) {
-        if (StringUtils.isEmpty((userAccount.getPassword()))) {
-            // 使用错误码100来判断
-            return error("100", "未设置密码");
-        } else {
-            // 校验密码
-            String encryPwd = userService.getEncryPassword(Const.ENCRY_FORMAT, password, userAccount.getSalt());
-            if (!encryPwd.equals(userAccount.getPassword())) {
-                return error("您输入的账号或密码有误");
-            }
+    /**
+     * 用户信息没问题,直接登录
+     *
+     * @param userAccount 用户账号信息
+     * @param returnUrl 跳转url
+     * @param userRecord 用户登录记录,便于记录登录时间,不能直接new出来
+     * @return
+     */
+    private ModelMap loginByUser(UserAccount userAccount, String returnUrl, UserRecord userRecord) {
+        /*
+         * 设置登录 Cookie 最后一个参数 true 时添加 cookie 同时销毁当前 JSESSIONID
+         * 创建信任的 JSESSIONID
+         */
+        SSOToken st = new SSOToken(request, userAccount.getMobile());
+        st.setData(JSON.toJSONString(userAccount));
+        SSOHelper.setSSOCookie(request, response, st, true);
 
-            // 登录
-            /*
-             * 设置登录 Cookie 最后一个参数 true 时添加 cookie 同时销毁当前 JSESSIONID
-             * 创建信任的 JSESSIONID
-             */
-            SSOToken st = new SSOToken(request, userAccount.getMobile());
-            st.setData(JSON.toJSONString(userAccount));
-            SSOHelper.setSSOCookie(request, response, st, true);
-
-            // 通知各个应用用户已经登录
-            ModelMap data = new ModelMap();
-            data = addOtherAppRequestData(userAccount, data, request.getSession().getAttribute("baseUrl"), true);
-            data.put("returnUrl", HttpUtil.decodeURL(returnUrl));
-            return success(data);
-        }
+        // 设置登录时间,并将密码输错次数设为0
+        userRecord.setLastLoginTime(System.currentTimeMillis());
+        userRecord.setPwdErrorCount(0);
+        userService.save(userRecord);
+
+        // 设置返回值,通知各个应用用户已经登录
+        ModelMap data = new ModelMap();
+        data = addOtherAppRequestData(userAccount, data, request.getSession().getAttribute("baseUrl"), true);
+        data.put("returnUrl", HttpUtil.decodeURL(returnUrl));
+        return success(data);
     }
 
     private ModelMap addOtherAppRequestData(UserAccount userAccount, ModelMap data, Object loginUrl,
                                             boolean isLoginAll) {
-        // 需要通知的应用数量
-        int count = 0;
         List<App> apps = appService.findAll();
         List<String> loginUrls = new ArrayList<>();
         boolean hasLoginUrl = false;
@@ -200,17 +267,14 @@ public class LoginController extends BaseController {
                     hasLoginUrl = true;
                 }
                 loginUrls.add(app.getLoginUrl());
-                count++;
             }
         }
 
         // 添加baseUrl
         if (!hasLoginUrl && !StringUtils.isEmpty(loginUrl)) {
             loginUrls.add(loginUrl.toString());
-            count++;
         }
 
-        data.put("count", count);
         data.put("loginUrls", loginUrls);
 
         // 添加传递数据
@@ -247,4 +311,29 @@ public class LoginController extends BaseController {
         return new ModelMap("spaces", spaces);
     }
 
+    @RequestMapping(value = "/checkCode", method = RequestMethod.GET)
+    public void checkCode() {
+        try {
+            // 获取验证码
+            CaptchaUtil.outputCaptcha(request, response, LOGIN_CAPTCHA);
+        } catch (ServletException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 获得密码输错次数
+     *
+     * @param username 用户名
+     * @return
+     */
+    @RequestMapping(value = "/getPwdErrorCount", method = RequestMethod.GET)
+    public ModelMap getPwdErrorCount(String username) {
+        if (StringUtils.isEmpty(username)) {
+            return error("用户名不能为空");
+        }
+        return success(userService.getPwdErrorCount(username));
+    }
 }

+ 9 - 4
sso-server/src/main/java/com/uas/sso/controller/PersonalRegisterController.java

@@ -22,7 +22,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
  * @date 2018/1/2
  */
 @Controller
-@RequestMapping("/sso/personal")
+@RequestMapping("/sso/personal/register")
 public class PersonalRegisterController extends BaseController {
 
     @Autowired
@@ -39,7 +39,7 @@ public class PersonalRegisterController extends BaseController {
      * @param token 验证码tokenId
      * @return 成功:success(),失败:error("错误码", "错误信息")
      */
-    @RequestMapping(value = "/register", method = RequestMethod.POST)
+    @RequestMapping(method = RequestMethod.POST)
     @ResponseBody
     public ModelMap register(User user, String appId, String code, String token) {
         // 获取参数
@@ -63,7 +63,7 @@ public class PersonalRegisterController extends BaseController {
         checkMobile(mobile, mobileArea);
 
         // 校验验证码
-        checkMobileCode(mobile, code, token);
+        checkMobileCode(token, mobile, code);
 
         // 校验密码
         if (PasswordStrength.WEAK.equals(checkPasswordLevel(password))) {
@@ -91,6 +91,11 @@ public class PersonalRegisterController extends BaseController {
     @RequestMapping(value = "/checkCode", method = RequestMethod.GET)
     @ResponseBody
     public ModelMap getCode(String mobile) {
+        // 参数校验
+        if (StringUtils.isEmpty(mobile)) {
+            return error("请输入手机号");
+        }
+
         // 获取验证码
         String token = getMobileCode(mobile);
 
@@ -113,7 +118,7 @@ public class PersonalRegisterController extends BaseController {
     public ModelMap checkCode(String token, String mobile, String code) {
         // 校验token是否正确
         String sessionToken = (String) request.getSession().getAttribute("token");
-        if (StringUtils.isEmpty(sessionToken) || sessionToken.equals(token)) {
+        if (StringUtils.isEmpty(sessionToken) || !sessionToken.equals(token)) {
             return error("请重新获取验证码");
         }
 

+ 366 - 0
sso-server/src/main/java/com/uas/sso/controller/ResetPasswordController.java

@@ -0,0 +1,366 @@
+package com.uas.sso.controller;
+
+import com.alibaba.fastjson.JSON;
+import com.uas.message.mail.service.MailService;
+import com.uas.sso.SSOHelper;
+import com.uas.sso.SSOToken;
+import com.uas.sso.core.Const;
+import com.uas.sso.core.PasswordStrength;
+import com.uas.sso.core.Status;
+import com.uas.sso.entity.*;
+import com.uas.sso.service.UserService;
+import com.uas.sso.util.CaptchaUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.ui.ModelMap;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+
+import javax.servlet.ServletException;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * 重置密码controller
+ *
+ * @author wangmh
+ * @date 2018/1/9.
+ */
+@RestController
+@RequestMapping(name = "/sso/resetPwd")
+public class ResetPasswordController extends BaseController {
+
+    @Autowired
+    private UserService userService;
+
+    @Autowired
+    private MailService mailService;
+
+    /**
+     * 重置密码验证码存session的key
+     */
+    private static final String RESET_CAPTCHA = "resetCaptcha";
+
+    /**
+     * 类型 重置密码
+     */
+    private static final String TYPE_RESET = "reset";
+
+    /**
+     * 类型 修改密码
+     */
+    private static final String TYPE_UPDATE = "update";
+
+    /**
+     * token有效期
+     */
+    private static final int EXPIRES = 24*60*60;
+
+    /**
+     * 找回密码校验手机号
+     * 根据手机号获取用户信息,之后修改密码直接使用这个信息
+     *
+     * @param mobile
+     * @return
+     */
+    @RequestMapping(value = "/checkCaptcha", method = RequestMethod.POST)
+    public ModelMap checkCaptcha(String mobile, String mobileArea, String captcha) {
+        // 校验手机号
+        User user = userService.findByMobile(mobile);
+        if (user == null) {
+            return error("用户不存在,请输入正确的手机号");
+        }
+
+        // 校验验证码
+        String resetCaptcha = (String) request.getSession().getAttribute(RESET_CAPTCHA);
+        if (StringUtils.isEmpty(resetCaptcha)) {
+            return error("未获取验证码");
+        }
+        if (!resetCaptcha.equals(captcha)) {
+            return error("请输入正确的验证码");
+        }
+
+        // 设置返回值
+        request.getSession().setAttribute("user", user);
+        return success();
+    }
+
+    /**
+     * 获取图片验证码
+     */
+    @RequestMapping(value = "/checkCaptcha", method = RequestMethod.GET)
+    public void checkCaptcha() {
+        try {
+            // 获取验证码
+            CaptchaUtil.outputCaptcha(request, response, RESET_CAPTCHA);
+        } catch (ServletException e) {
+            e.printStackTrace();
+        } catch (IOException e) {
+            e.printStackTrace();
+        }
+    }
+
+    /**
+     * 获取可以校验方式
+     *
+     * @param type 修改密码类型(update or reset)
+     * @return
+     */
+    @RequestMapping(value = "/CheckType/{type}", method = RequestMethod.GET)
+    public ModelMap getCheckType(@PathVariable String type) {
+        // 找到用户信息
+        User user = null;
+        if (TYPE_RESET.equals(type)) {
+            // 调用类型为重置密码,重置密码可以通过session获得用户信息
+            user = (User) request.getSession().getAttribute("user");
+            if (user == null) {
+                return error("请求超时,请刷新重试!");
+            }
+        } else if (TYPE_UPDATE.equals(type)) {
+            // 调用类型为修改密码,修改密码可以通过cookie获得用户信息
+            SSOToken token = SSOHelper.getToken(request);
+            UserAccount userAccount = JSON.parseObject(token.getData(), UserAccount.class);
+            user = userService.findOne(userAccount.getUserUU());
+        }
+
+        // 设置返回数据
+        ModelMap data = new ModelMap();
+        data.put("mobile", Status.AUTHENTICATED.getCode() == user.getMobileValidCode() ? user.getMobile() : null);
+        data.put("email", Status.AUTHENTICATED.getCode() == user.getEmailValidCode() ? user.getEmail() : null);
+        request.getSession().setAttribute("user", user);
+        return success(data);
+    }
+
+    /**
+     * 重置密码第一步设置token
+     * @param userUU 用户uu号
+     * @return tokenId
+     */
+    private String setToken(Long userUU) {
+
+        Token token = new Token(userUU, EXPIRES);
+        return token.getId();
+    }
+
+    /**
+     * 通过密码重置密码
+     * @param password 密码
+     * @return
+     */
+    @RequestMapping(value = "/check/password", method = RequestMethod.POST)
+    public ModelMap checkByPassword(String password) {
+        // 通过session获取当前找回密码的用户
+        User user = (User) request.getSession().getAttribute("user");
+        if (StringUtils.isEmpty(user)) {
+            return error("请求超时,请刷新重试!");
+        }
+
+        // 校验密码
+        String encryPwd = userService.getEncryPassword(Const.ENCRY_FORMAT, password, user.getSalt());
+        if (!encryPwd.equals(password)) {
+            return error("密码错误");
+        }
+
+        // 设置token,并返回
+        String tokenId = setToken(user.getUserUU());
+        return success(new ModelMap("token", tokenId));
+    }
+
+    /**
+     * 通过手机号重置密码,获取验证码
+     * @return
+     */
+    @RequestMapping(value = "/check/mobile", method = RequestMethod.GET)
+    public ModelMap checkByMobile() {
+        // 从session中获取用户信息
+        User user = (User) request.getSession().getAttribute("user");
+        if (StringUtils.isEmpty(user)) {
+            return error("请求超时,请刷新重试!");
+        }
+
+        // 获取验证码
+        String token = getMobileCode(user.getMobile());
+
+        // 设置返回数据
+        ModelMap data = new ModelMap();
+        data.put("token", token);
+        request.getSession().setAttribute("token", token);
+        return success(data);
+    }
+
+    /**
+     * 通过手机号重置密码,校验验证码
+     *
+     * @param code 用户输入的验证码
+     * @param token 验证码id
+     * @return
+     */
+    @RequestMapping(value = "/check/mobile", method = RequestMethod.POST)
+    public ModelMap checkByMobile(String code, String token) {
+        // 从session中获取用户信息
+        User user = (User) request.getSession().getAttribute("user");
+        if (StringUtils.isEmpty(user)) {
+            return error("请求超时,请刷新重试!");
+        }
+
+        // 校验token是否正确
+        String sessionToken = (String) request.getSession().getAttribute("token");
+        if (StringUtils.isEmpty(sessionToken) || sessionToken.equals(token)) {
+            return error("请重新获取验证码");
+        }
+        if (StringUtils.isEmpty(code)) {
+            return error("请输入验证码");
+        }
+
+        // 校验验证码并删除token
+        checkMobileCode(token, user.getMobile(), code);
+        tokenService.delete(token);
+
+        // 设置token,并返回
+        String tokenId = setToken(user.getUserUU());
+        return success(new ModelMap("token", tokenId));
+    }
+
+    /**
+     * 通过邮箱重置密码,发送邮箱确认
+     *
+     * @return
+     */
+    @RequestMapping(value = "/check/email", method = RequestMethod.GET)
+    public ModelMap checkByEmail() {
+        // 从session中获取用户信息
+        User user = (User) request.getSession().getAttribute("user");
+        if (StringUtils.isEmpty(user)) {
+            return error("请求超时,请刷新重试!");
+        }
+
+        // 设置发送邮件信息
+        int expires = 24*60*60;
+        Token token = new Token("user", expires);
+        ModelMap data = new ModelMap();
+        data.put("vipName", user.getVipName());
+        // TODO 邮件认证地址
+        data.put("url", "http://192.168.253.66:8081/sso/resetPwd/check/question?token="+token);
+
+        // 发送邮件
+        String email = user.getEmail();
+        if (!StringUtils.isEmpty(email)) {
+            Setting mailTplId = settingService.findOne("templateForSendMailWhenResetPassword");
+            if (!StringUtils.isEmpty(mailTplId)) {
+                mailService.send(mailTplId.getValue(), email, data);
+            }
+        }
+
+        return success();
+    }
+
+    /**
+     * 重置密码第二步,认证密保
+     * @param token
+     * @return
+     */
+    @RequestMapping(value = "/check/question", method = RequestMethod.GET)
+    public ModelMap checkByQuestion(String token) {
+        // 校验token
+        if (StringUtils.isEmpty(token)) {
+            return error("请刷新重试");
+        }
+        Token existToken = tokenService.findOne(token);
+        if (existToken == null) {
+            return error("认证信息已过期,清刷新重试!");
+        }
+
+        // 查询密保
+        Long userUU = (Long) existToken.getBind();
+        User user = userService.findOne(userUU);
+        if (user == null) {
+            return error("认证信息错误,清刷新重试!");
+        }
+        tokenService.delete(token);
+
+        // 返回用户密保,token
+        existToken = new Token(user, EXPIRES);
+        ModelMap data = new ModelMap();
+        data.put("token",existToken.getId());
+        data.put("question", user.getQuestions());
+        return success(data);
+    }
+
+    /**
+     * 重置密码第二步,认证密保
+     * @param token
+     * @return
+     */
+    @RequestMapping(value = "/check/question", method = RequestMethod.POST)
+    public ModelMap checkByQuestion(String token, List<Map<String, Object>> answers) {
+        // 校验token是否正确
+        if (StringUtils.isEmpty(token)) {
+            return error("请刷新重试");
+        }
+        Token expireToken = tokenService.findOne(token);
+        if (expireToken == null) {
+            return error("请求超时,请刷新重试");
+        }
+
+        // 校验密保答案
+        User user = (User) expireToken.getBind();
+        List<UserQuestion> questions = user.getQuestions();
+        Map<Long, String> userAnswer = new HashMap<>(questions.size());
+        for (UserQuestion question : questions) {
+            userAnswer.put(question.getId(), question.getAnswer());
+        }
+        for (Map<String, Object> answer : answers) {
+            if (!answer.get("answer").equals(userAnswer.get(answer.get("id")))){
+                return error("答案错误");
+            }
+        }
+
+        tokenService.delete(token);
+
+        // 返回token
+        expireToken = new Token(user, EXPIRES);
+        ModelMap data = new ModelMap();
+        data.put("token", expireToken.getId());
+        return success(data);
+    }
+
+    /**
+     * 重置密码第三步,重置密码
+     * @param password 新密码
+     * @param token tokenId,包含用户信息
+     * @return
+     */
+    @RequestMapping(method = RequestMethod.POST)
+    public ModelMap resetPassword(String password, String token) {
+        // 校验token是否正确
+        if (StringUtils.isEmpty(token)) {
+            return error("请刷新重试");
+        }
+        Token expireToken = tokenService.findOne(token);
+        if (expireToken == null) {
+            return error("请求超时,请刷新重试");
+        }
+
+        // 校验密码
+        PasswordStrength passwordStrength = checkPasswordLevel(password);
+        if (PasswordStrength.WEAK.getValue() == passwordStrength.getValue()) {
+            return error("密码须为8-20字符的英文、数字混合");
+        }
+
+        // 从token中获取用户信息
+        User user = (User) expireToken.getBind();
+
+        // 设置加密后的密码
+        String encryPasswird = userService.getEncryPassword(Const.ENCRY_FORMAT, password, user.getSalt());
+        user.setPassword(encryPasswird);
+        userService.save(user);
+
+        // 删除token,返回成功
+        tokenService.delete(token);
+        return success();
+    }
+}

+ 329 - 0
sso-server/src/main/java/com/uas/sso/controller/UpdateUserController.java

@@ -0,0 +1,329 @@
+package com.uas.sso.controller;
+
+import com.uas.sso.core.Status;
+import com.uas.sso.entity.*;
+import com.uas.sso.service.UserService;
+import com.uas.sso.support.SystemSession;
+import com.uas.sso.util.CollectionUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.ui.ModelMap;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * @author wangmh
+ * @create 2018-01-11 17:11
+ * @desc 修改用户信息(需要登录)
+ **/
+@RestController
+@RequestMapping("/update/user")
+public class UpdateUserController extends BaseController {
+
+    @Autowired
+    private UserService userService;
+
+    /**
+     * 校验信息token有效期
+     */
+    private static final int EXPIRES = 7*24*60*60;
+
+    /**
+     * 获取可以校验方式
+     *
+     * @return
+     */
+    @RequestMapping(value = "/CheckType", method = RequestMethod.GET)
+    public ModelMap getCheckType() {
+        // 获取用户信息
+        UserAccount userAccount = SystemSession.getUserAccount();
+        User user = userService.findOne(userAccount.getUserUU());
+
+        // 设置返回数据
+        ModelMap data = new ModelMap();
+        data.put("mobile", Status.AUTHENTICATED.getCode() == user.getMobileValidCode() ? user.getMobile() : null);
+        data.put("email", Status.AUTHENTICATED.getCode() == user.getEmailValidCode() ? user.getEmail() : null);
+        data.put("question", CollectionUtils.isEmpty(user.getQuestions()) ? user.getQuestions() : null);
+        request.getSession().setAttribute("user", user);
+        return success();
+    }
+
+    /**
+     * 获取校验手机号验证码
+     *
+     * @author wangmh
+     * @date 2018/1/11 20:16
+     * @param mobile 手机号
+     * @return
+     */
+    @RequestMapping(value = "/check/mobile", method = RequestMethod.GET)
+    public ModelMap checkByMobile(String mobile) {
+        // 获取验证码
+        String token = getMobileCode(mobile);
+
+        // 设置返回数据
+        ModelMap data = new ModelMap();
+        data.put("token", token);
+        request.getSession().setAttribute("token", token);
+        return success(data);
+    }
+
+    /**
+     * 校验手机号验证码
+     *
+     * @author wangmh
+     * @date 2018/1/11 20:17
+     * @param mobile 手机号
+     * @param code 验证码
+     * @param token 验证码token
+     * @return
+     */
+    @RequestMapping(value = "/check/mobile", method = RequestMethod.POST)
+    public ModelMap checkByMobile(String mobile, String code, @RequestParam String token) {
+        // 校验空参数
+        if (StringUtils.isEmpty(mobile)) {
+            return error("手机号不能为空");
+        }
+        if (StringUtils.isEmpty(code)) {
+            return error("验证码不能为空");
+        }
+
+        // 校验token
+        Token existToken = tokenService.findOne(token);
+        if (existToken == null) {
+            return error("请重新获取验证码");
+        }
+
+        // 校验验证码
+        checkMobileCode(token, mobile, code);
+        tokenService.delete(token);
+
+        // 设置返回数据
+        User user = userService.findByMobile(mobile);
+        existToken = new Token(user, EXPIRES);
+        return success(existToken.getId());
+    }
+
+
+    /**
+     * 通过邮箱重置密码,发送邮箱确认
+     *
+     * @return
+     */
+    @RequestMapping(value = "/check/email", method = RequestMethod.GET)
+    public ModelMap checkByEmail(String operate, @RequestParam String email) {
+        // 校验空参数
+        if (StringUtils.isEmpty(email)) {
+            return error("手机号不能为空");
+        }
+
+        // 根据邮箱找到用户
+        User user = userService.findByUsername(email);
+
+        // 设置发送邮件信息
+        Token token = new Token(user, EXPIRES);
+        ModelMap data = new ModelMap();
+        data.put("vipName", user.getVipName());
+        // TODO 邮件认证地址
+        if ("mobile".equals(operate)) {
+            data.put("url", "http://192.168.253.66:8081/update/user/setMobile?token=" + token);
+        } else if ("email".equals(operate)) {
+            data.put("url", "http://192.168.253.66:8081/update/user/setMail?token=" + token);
+        }
+
+        // 发送邮件
+        if (!StringUtils.isEmpty(email)) {
+            Setting mailTplId = settingService.findOne("templateForSendMailWhenResetPassword");
+            if (!StringUtils.isEmpty(mailTplId)) {
+                mailService.send(mailTplId.getValue(), email, data);
+            }
+        }
+
+        return success();
+    }
+
+    /**
+     * 重置密码第二步,认证密保
+     * @param answers 密保答案
+     * @return
+     */
+    @RequestMapping(value = "/check/question", method = RequestMethod.POST)
+    public ModelMap checkByQuestion(List<Map<String, Object>> answers) {
+
+        // 校验密保答案
+        User user = (User) request.getSession().getAttribute("user");
+        List<UserQuestion> questions = user.getQuestions();
+        Map<Long, String> userAnswer = new HashMap<>(questions.size());
+        for (UserQuestion question : questions) {
+            userAnswer.put(question.getId(), question.getAnswer());
+        }
+        for (Map<String, Object> answer : answers) {
+            if (!answer.get("answer").equals(userAnswer.get(answer.get("id")))){
+                return error("答案错误");
+            }
+        }
+
+        // 返回token
+        Token expireToken = new Token(user, EXPIRES);
+        ModelMap data = new ModelMap();
+        data.put("token", expireToken.getId());
+        return success(data);
+    }
+
+    /**
+     * 设置手机号校验获取验证码
+     *
+     * @param mobile 获取验证码手机号
+     * @param token 第一步传递的tokenId
+     * @return
+     */
+    @RequestMapping(value = "/setMobile", method = RequestMethod.GET)
+    public ModelMap updateMobile(String mobile, @RequestParam String token) {
+        // 校验token
+        Token existToken = tokenService.findOne(token);
+        if (existToken == null || existToken.isExpired()) {
+            return error("请求超时");
+        }
+
+        // 拿出user放入session中
+        User user = (User) existToken.getBind();
+        if (user == null) {
+            return error("请求错误");
+        }
+        tokenService.delete(token);
+
+        // 获取验证码
+        token = getMobileCode(mobile);
+
+        request.getSession().setAttribute("user", user);
+        return success(new ModelMap("token", token));
+    }
+
+    /**
+     * 设置手机号
+     *
+     * @author wangmh
+     * @date 2018/1/11 21:15
+     * @param mobile 手机号
+     * @param code 验证码
+     * @param token 验证码tokenId
+     * @return
+     */
+    @RequestMapping(value = "/setMobile", method = RequestMethod.POST)
+    public ModelMap updateMobile(String mobile, String code, @RequestParam String token) {
+        // 校验空参数
+        if (StringUtils.isEmpty(mobile)) {
+            return error("手机号不能为空");
+        }
+        if (StringUtils.isEmpty(code)) {
+            return error("验证码不能为空");
+        }
+
+        // 从session中获取用户信息
+        User user = (User) request.getSession().getAttribute("user");
+        if (user == null) {
+            return error("请求超时,请刷新重试");
+        }
+
+        // 校验手机号是否被使用
+        if (userService.mobileHasRegistered(mobile)){
+            return error("手机号已注册");
+        }
+
+        // 校验token
+        Token existToken = tokenService.findOne(token);
+        if (existToken == null) {
+            return error("请重新获取验证码");
+        }
+
+        // 校验验证码
+        checkMobileCode(token, mobile, code);
+        tokenService.delete(token);
+
+        // 修改手机号
+        userService.updateMobile(user.getUserUU(), mobile);
+        return success();
+    }
+
+    /**
+     * 修改邮箱,获取校验邮箱验证码
+     *
+     * @author wangmh
+     * @date 2018/1/11 20:16
+     * @param email 邮箱
+     * @return
+     */
+    @RequestMapping(value = "/setEmail", method = RequestMethod.GET)
+    public ModelMap updateEmail(String email, @RequestParam String token) {
+        // 校验token
+        Token existToken = tokenService.findOne(token);
+        if (existToken == null || existToken.isExpired()) {
+            return error("请求超时");
+        }
+
+        // 拿出user放入session中
+        User user = (User) existToken.getBind();
+        if (user == null) {
+            return error("请求错误");
+        }
+        tokenService.delete(token);
+
+        // 获取验证码
+        token = getEmailCode(email);
+
+        request.getSession().setAttribute("user", user);
+        return success(new ModelMap("token", token));
+    }
+
+    /**
+     * 设置手机号
+     *
+     * @author wangmh
+     * @date 2018/1/11 21:15
+     * @param email 邮箱
+     * @param code 验证码
+     * @param token 验证码tokenId
+     * @return
+     */
+    @RequestMapping(value = "/setEmail", method = RequestMethod.POST)
+    public ModelMap updateEmail(String email, String code, @RequestParam String token) {
+        // 校验空参数
+        if (StringUtils.isEmpty(email)) {
+            return error("邮箱不能为空");
+        }
+        if (StringUtils.isEmpty(code)) {
+            return error("验证码不能为空");
+        }
+
+        // 从session中获取用户信息
+        User user = (User) request.getSession().getAttribute("user");
+        if (user == null) {
+            return error("请求超时,请刷新重试");
+        }
+
+        // 校验手机号是否被使用
+        if (userService.emailHasRegistered(email)){
+            return error("邮箱已注册");
+        }
+
+        // 校验token
+        Token existToken = tokenService.findOne(token);
+        if (existToken == null) {
+            return error("请重新获取验证码");
+        }
+
+        // 校验验证码
+        checkEmailCode(token, email, code);
+        tokenService.delete(token);
+
+        // 修改邮箱
+        userService.updateEmail(user.getUserUU(), email);
+        return success();
+    }
+}

+ 28 - 5
sso-server/src/main/java/com/uas/sso/controller/UserManagerController.java

@@ -1,13 +1,11 @@
 package com.uas.sso.controller;
 
-import com.uas.sso.entity.User;
 import com.uas.sso.service.UserService;
 import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Controller;
 import org.springframework.ui.ModelMap;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RequestMethod;
-import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
 
 /**
  * 用户信息管理controller
@@ -15,7 +13,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
  * @author wangmh
  * @date 2018/1/2
  */
-@Controller
+@RestController
 @RequestMapping("/api/user")
 public class UserManagerController extends BaseController {
 
@@ -29,8 +27,33 @@ public class UserManagerController extends BaseController {
      * @return
      */
     @RequestMapping(value = "/checkMobile", method = RequestMethod.GET)
-    @ResponseBody
     public ModelMap checkMobile(String mobile) {
         return new ModelMap("hasRegister", userService.mobileHasRegistered(mobile));
     }
+
+    /**
+     * 校验真实姓名是否被认证
+     *
+     * @author wangmh
+     * @date 2018/1/11 15:05
+     * @param realName 真实姓名
+     * @return
+     */
+    @RequestMapping(value = "/realName/valid", method = RequestMethod.GET)
+    public ModelMap realNameIsValid(String realName) {
+        return success(new ModelMap("isValid", userService.realNameIsValid(realName)));
+    }
+
+    /**
+     * 校验身份证号是否被认证
+     *
+     * @author wangmh
+     * @date 2018/1/11 15:06
+     * @param idCard 身份证号
+     * @return
+     */
+    @RequestMapping(value = "/idCard/valid", method = RequestMethod.GET)
+    public ModelMap idCardIsValid(String idCard) {
+        return success(new ModelMap("isValid", userService.idCardIsValid(idCard)));
+    }
 }

+ 29 - 3
sso-server/src/main/java/com/uas/sso/controller/UserspaceManageController.java

@@ -5,7 +5,9 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Controller;
 import org.springframework.ui.ModelMap;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
 import org.springframework.web.bind.annotation.ResponseBody;
+import org.springframework.web.bind.annotation.RestController;
 
 /**
  * 企业信息管理controller
@@ -13,7 +15,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
  * @author wangmh
  * @date 2018/1/5
  */
-@Controller
+@RestController
 @RequestMapping("/api/userspace")
 public class UserspaceManageController extends BaseController {
 
@@ -27,7 +29,6 @@ public class UserspaceManageController extends BaseController {
      * @return
      */
     @RequestMapping("/checkSpaceName")
-    @ResponseBody
     public ModelMap checkSpaceName(String spaceName) {
         userspaceService.checkSpaceName(spaceName);
         return success();
@@ -40,9 +41,34 @@ public class UserspaceManageController extends BaseController {
      * @return
      */
     @RequestMapping("/checkBusinessCode")
-    @ResponseBody
     public ModelMap checkBusinessCode(String businessCode) {
         userspaceService.checkBusinessCode(businessCode);
         return success();
     }
+
+    /**
+     * 校验企业是否被认证
+     *
+     * @author wangmh
+     * @date 2018/1/11 20:51
+     * @param spaceName 企业名称
+     * @return
+     */
+    @RequestMapping(value = "/name/valid", method = RequestMethod.GET)
+    public ModelMap spaceNameIsValid(String spaceName) {
+        return success(new ModelMap("isValid", userspaceService.spaceNameIsValid(spaceName)));
+    }
+
+    /**
+     * 校验营业执照号是否被认证
+     * 
+     * @author wangmh
+     * @date 2018/1/11 10:35
+     * @param businessCode 营业执照号
+     * @return
+     */
+    @RequestMapping(value = "/businessCode/valid", method = RequestMethod.GET)
+    public ModelMap businessCodeIsValid(String businessCode) {
+        return success(new ModelMap("isValid", userspaceService.businessCodeIsValid(businessCode)));
+    }
 }

+ 1 - 1
sso-server/src/main/java/com/uas/sso/controller/UserspaceRegisterController.java

@@ -23,7 +23,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
  * @author wangmh
  * @date 2018/1/4
  */
-@RequestMapping("/sso/register")
+@RequestMapping("/sso/userspace/register")
 @Controller
 public class UserspaceRegisterController extends BaseController {
 

+ 116 - 0
sso-server/src/main/java/com/uas/sso/controller/ValidController.java

@@ -0,0 +1,116 @@
+package com.uas.sso.controller;
+
+import com.alibaba.fastjson.JSONObject;
+import com.uas.sso.entity.User;
+import com.uas.sso.entity.Userspace;
+import com.uas.sso.service.UserService;
+import com.uas.sso.service.UserspaceService;
+import com.uas.sso.util.FastjsonUtils;
+import com.uas.sso.util.FileUrl;
+import com.uas.sso.util.HttpUtils;
+import com.uas.sso.util.ParameterUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.ui.ModelMap;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestMethod;
+import org.springframework.web.bind.annotation.RestController;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 认证信息controller
+ * @author wangmh
+ * @date 2018/1/11.
+ */
+@RestController
+@RequestMapping("/valid")
+public class ValidController extends BaseController {
+
+    @Autowired
+    private UserspaceService userspaceService;
+
+    @Autowired
+    private UserService userService;
+
+    /**
+     * 图片最大5M
+     */
+    private static final int IMAGE_MAX_SIZE = 5 * 1024 * 1024;
+
+    /**
+     * 提交企业认证信息
+     *
+     * @author wangmh
+     * @date 2018/1/11 14:38
+     * @param userspace 企业信息
+     * @param businessImage 营业执照号
+     * @return
+     * @throws Exception
+     */
+    @RequestMapping(value = "/userspace/submit", method = RequestMethod.POST)
+    public ModelMap submitSpaceInfo(Userspace userspace, @RequestBody MultipartFile businessImage) throws Exception {
+        // 获取参数
+        String spaceName = userspace.getSpaceName();
+        String businessCode = userspace.getBusinessCode();
+        String corporation = userspace.getCorporation();
+        String regAddress = userspace.getRegAddress();
+
+        // 参数空校验
+        Map<String, String> params = new HashMap<>(4);
+        params.put("企业名", spaceName);
+        params.put("营业执照号", businessCode);
+        params.put("法定代表人", corporation);
+        params.put("注册地址", regAddress);
+        ParameterUtils.checkEmptyParameter(params);
+
+        // 上传营业执照
+        if (!(businessImage == null || businessImage.isEmpty())) {
+            if (businessImage.getSize() > IMAGE_MAX_SIZE) {
+                return error("营业执照附件大小不要超过5M");
+            }
+            HttpUtils.Response response = HttpUtils.upload(FileUrl.FILE_UPLOAD, businessImage, null);
+            JSONObject obj = FastjsonUtils.parseObject(response.getResponseText());
+            String path = (String) obj.get("path");
+            if (path != null) {
+                userspace.setBusinessCodeImage(path);
+            } else {
+                return error("请检查您的营业执照附件");
+            }
+        }
+
+        // 将企业添加到待认证
+        userspaceService.submitValidInfo(userspace);
+
+        return success();
+    }
+
+    /**
+     * 用户提交身份认证信息
+     *
+     * @author wangmh
+     * @date 2018/1/11 15:21
+     * @param realName 真实姓名
+     * @param idCard 身份证号
+     * @return
+     * @throws Exception
+     */
+    @RequestMapping(value = "/user/identity/submit", method = RequestMethod.POST)
+    public ModelMap submitUserIdentityInfo(String realName, String idCard) throws Exception {
+        // 参数空校验
+        Map<String, String> params = new HashMap<>(2);
+        params.put("真实姓名", realName);
+        params.put("身份证号", idCard);
+        ParameterUtils.checkEmptyParameter(params);
+
+        // 将实名认证添加到待认证
+        User user = new User();
+        user.setRealName(realName);
+        user.setIdCard(idCard);
+        userService.submitIdValidInfo(user);
+
+        return success();
+    }
+}

+ 13 - 0
sso-server/src/main/java/com/uas/sso/dao/ChangeAdminDao.java

@@ -0,0 +1,13 @@
+package com.uas.sso.dao;
+
+import com.uas.sso.entity.ChangeAdmin;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+/**
+ * @author wangmh
+ * @create 2018-01-15 19:36
+ * @desc
+ **/
+public interface ChangeAdminDao extends JpaRepository<ChangeAdmin, Long>, JpaSpecificationExecutor<ChangeAdmin> {
+}

+ 13 - 0
sso-server/src/main/java/com/uas/sso/dao/ResetPwdAppealDao.java

@@ -0,0 +1,13 @@
+package com.uas.sso.dao;
+
+import com.uas.sso.entity.ResetPwdAppeal;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+
+/**
+ * @author wangmh
+ * @create 2018-01-16 14:27
+ * @desc
+ **/
+public interface ResetPwdAppealDao extends JpaRepository<ResetPwdAppeal, Long>, JpaSpecificationExecutor<ResetPwdAppeal> {
+}

+ 20 - 0
sso-server/src/main/java/com/uas/sso/dao/UserDao.java

@@ -63,4 +63,24 @@ public interface UserDao extends JpaRepository<User, Long>, JpaSpecificationExec
      * @return
      */
     List<User> findByEmailAndEmailValidCode(String email, Short emailValidCode);
+
+    /**
+     * 根据用户真实姓名找到用户信息
+     *
+     * @author wangmh
+     * @date 2018/1/11 14:49
+     * @param realName 真实姓名
+     * @return
+     */
+    User findByRealName(String realName);
+
+    /**
+     * 根据用户身份证找到用户信息
+     *
+     * @author wangmh
+     * @date 2018/1/11 14:58
+     * @param idCard
+     * @return
+     */
+    User findByIdCard(String idCard);
 }

+ 21 - 0
sso-server/src/main/java/com/uas/sso/dao/UserRecordDao.java

@@ -0,0 +1,21 @@
+package com.uas.sso.dao;
+
+import com.uas.sso.entity.UserRecord;
+import org.springframework.data.jpa.repository.JpaRepository;
+import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
+import org.springframework.data.jpa.repository.Query;
+
+/**
+ * 用户登录记录Dao
+ *
+ * @author wangmh
+ * @date 2018/1/9.
+ */
+public interface UserRecordDao extends JpaRepository<UserRecord, Long>, JpaSpecificationExecutor<UserRecord> {
+
+    /**
+     * 将所有用户密码输错次数设为0
+     */
+    @Query("update UserRecord u set u.pwdErrorCount = 0")
+    void clearPwdErrorCount();
+}

+ 177 - 0
sso-server/src/main/java/com/uas/sso/entity/ChangeAdmin.java

@@ -0,0 +1,177 @@
+package com.uas.sso.entity;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+/**
+ * @author wangmh
+ * @create 2018-01-15 18:33
+ * @desc 更换管理员实体
+ **/
+@Entity
+@Table(name = "sso$us$admin")
+public class ChangeAdmin implements Serializable {
+
+    /**
+     *
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @Id
+    @Column(name = "_id")
+    @SequenceGenerator(name="sso$us$admin_gen", sequenceName="sso$us$admin_seq", allocationSize=1)
+    @GeneratedValue(strategy=GenerationType.IDENTITY, generator="sso$us$admin_gen")
+    private Long id;
+
+    /**
+     * 提交人uu号
+     */
+    @Column(name = "submitteruu", nullable = false)
+    private Long submitterUU;
+
+    /**
+     * 提交时间
+     */
+    @Column(name = "submit_time", nullable = false)
+    private Timestamp submitDate;
+
+    /**
+     * 更换管理员原因
+     */
+    @Column(name = "change_reason", length = 1000, nullable = false)
+    private String changeReason;
+
+    /**
+     * 更换前管理员的uu号
+     */
+    @Column(name = "before_admin_uu")
+    private Long beforeAdminUU;
+
+    /**
+     * 更换后管理员的uu号
+     */
+    @Column(name = "after_admin_uu")
+    private Long afterAdminUU;
+
+    /**
+     * 审核人
+     */
+    @Column(name = "auditor")
+    private String auditor;
+
+    /**
+     * 认证日期
+     */
+    @Column(name = "valid_date")
+    private String validDate;
+
+    /**
+     * 认证状态
+     */
+    @Column(name = "valid_code", nullable = false)
+    private Short validCode;
+
+    /**
+     * 不通过原因
+     */
+    @Column(name = "invalid_reason")
+    private String invalidReason;
+
+    /**
+     * 联系人电话
+     */
+    @Column(name = "contact_tel")
+    private String contactTel;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getSubmitterUU() {
+        return submitterUU;
+    }
+
+    public void setSubmitterUU(Long submitterUU) {
+        this.submitterUU = submitterUU;
+    }
+
+    public Timestamp getSubmitDate() {
+        return submitDate;
+    }
+
+    public void setSubmitDate(Timestamp submitDate) {
+        this.submitDate = submitDate;
+    }
+
+    public String getChangeReason() {
+        return changeReason;
+    }
+
+    public void setChangeReason(String changeReason) {
+        this.changeReason = changeReason;
+    }
+
+    public Long getBeforeAdminUU() {
+        return beforeAdminUU;
+    }
+
+    public void setBeforeAdminUU(Long beforeAdminUU) {
+        this.beforeAdminUU = beforeAdminUU;
+    }
+
+    public Long getAfterAdminUU() {
+        return afterAdminUU;
+    }
+
+    public void setAfterAdminUU(Long afterAdminUU) {
+        this.afterAdminUU = afterAdminUU;
+    }
+
+    public String getAuditor() {
+        return auditor;
+    }
+
+    public void setAuditor(String auditor) {
+        this.auditor = auditor;
+    }
+
+    public String getValidDate() {
+        return validDate;
+    }
+
+    public void setValidDate(String validDate) {
+        this.validDate = validDate;
+    }
+
+    public Short getValidCode() {
+        return validCode;
+    }
+
+    public void setValidCode(Short validCode) {
+        this.validCode = validCode;
+    }
+
+    public String getInvalidReason() {
+        return invalidReason;
+    }
+
+    public void setInvalidReason(String invalidReason) {
+        this.invalidReason = invalidReason;
+    }
+
+    public String getContactTel() {
+        return contactTel;
+    }
+
+    public void setContactTel(String contactTel) {
+        this.contactTel = contactTel;
+    }
+}

+ 149 - 0
sso-server/src/main/java/com/uas/sso/entity/ResetPwdAppeal.java

@@ -0,0 +1,149 @@
+package com.uas.sso.entity;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * @author wangmh
+ * @create 2018-01-16 10:58
+ * @desc 找回密码申述实体
+ **/
+@Entity
+@Table(name = "sso$appeal$password")
+public class ResetPwdAppeal implements Serializable {
+
+
+    /**
+     *
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @Id
+    @Column(name = "_id")
+    @SequenceGenerator(name = "sso$appeal$password_gen", sequenceName = "sso$appeal$password_seq", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "sso$appeal$password_gen")
+    private Long id;
+
+    /**
+     * 手机号
+     */
+    @Column(name = "mobile", nullable = false)
+    private String mobile;
+
+    /**
+     * 申述密码
+     */
+    @Column(name = "_password", nullable = false)
+    private String password;
+
+    /**
+     * 联系人
+     */
+    @Column(name = "contact_name", nullable = false)
+    private String contactName;
+
+    /**
+     * 联系人
+     */
+    @Column(name = "contact_tel", nullable = false)
+    private String contactTel;
+
+    /**
+     * 联系人
+     */
+    @Column(name = "contact_email", nullable = false)
+    private String contactEmail;
+
+    /**
+     * 审核人
+     */
+    @Column(name = "auditor")
+    private String auditor;
+
+    /**
+     * 审核日期
+     */
+    @Column(name = "audit_date")
+    private String auditDate;
+
+    /**
+     * 审核状态(Status枚举)
+     */
+    @Column(name = "status", nullable = false)
+    private short status;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public String getMobile() {
+        return mobile;
+    }
+
+    public void setMobile(String mobile) {
+        this.mobile = mobile;
+    }
+
+    public String getPassword() {
+        return password;
+    }
+
+    public void setPassword(String password) {
+        this.password = password;
+    }
+
+    public String getContactName() {
+        return contactName;
+    }
+
+    public void setContactName(String contactName) {
+        this.contactName = contactName;
+    }
+
+    public String getContactTel() {
+        return contactTel;
+    }
+
+    public void setContactTel(String contactTel) {
+        this.contactTel = contactTel;
+    }
+
+    public String getContactEmail() {
+        return contactEmail;
+    }
+
+    public void setContactEmail(String contactEmail) {
+        this.contactEmail = contactEmail;
+    }
+
+    public String getAuditor() {
+        return auditor;
+    }
+
+    public void setAuditor(String auditor) {
+        this.auditor = auditor;
+    }
+
+    public String getAuditDate() {
+        return auditDate;
+    }
+
+    public void setAuditDate(String auditDate) {
+        this.auditDate = auditDate;
+    }
+
+    public short getStatus() {
+        return status;
+    }
+
+    public void setStatus(short status) {
+        this.status = status;
+    }
+}

+ 18 - 0
sso-server/src/main/java/com/uas/sso/entity/Token.java

@@ -5,6 +5,9 @@ import com.uas.sso.util.StringUtil;
 import java.io.Serializable;
 import java.util.Date;
 
+/**
+ * @author wangmh
+ */
 public class Token implements Serializable {
 
 	/**
@@ -22,6 +25,8 @@ public class Token implements Serializable {
 
     private String mobile;
 
+    private String email;
+
 	/**
 	 * 60秒过期
 	 */
@@ -98,4 +103,17 @@ public class Token implements Serializable {
     public void setMobile(String mobile) {
         this.mobile = mobile;
     }
+
+	/**
+	 * 绑定邮箱
+	 *
+	 * @return
+	 */
+	public String getEmail() {
+		return email;
+	}
+
+	public void setEmail(String email) {
+		this.email = email;
+	}
 }

+ 33 - 2
sso-server/src/main/java/com/uas/sso/entity/User.java

@@ -3,6 +3,7 @@ package com.uas.sso.entity;
 import javax.persistence.*;
 import java.io.Serializable;
 import java.sql.Timestamp;
+import java.util.List;
 
 /**
  * 用户信息
@@ -89,7 +90,7 @@ public class User implements Serializable {
     /**
      * 用户真实姓名
      */
-    @Column(name = "real_name")
+    @Column(name = "real_name", unique = true)
     private String realName;
 
     /**
@@ -101,7 +102,7 @@ public class User implements Serializable {
     /**
      * 用户身份认证状态
      */
-    @Column(name = "identity_valid_code")
+    @Column(name = "identity_valid_code", nullable = false)
     private Short identityValidCode;
 
     /**
@@ -170,6 +171,20 @@ public class User implements Serializable {
     @Column(name = "_lock")
     private Integer lock;
 
+    @OneToOne(fetch = FetchType.LAZY, cascade = {CascadeType.PERSIST})
+    @JoinColumn(name = "record_id")
+    private UserRecord userRecord;
+
+    /**
+     * 密保问题
+     */
+    @OneToMany(fetch = FetchType.LAZY, cascade = {CascadeType.REMOVE})
+    @JoinColumn(name = "useruu", nullable = false)
+    private List<UserQuestion> questions;
+
+    public User() {
+    }
+
     public Long getUserUU() {
         return userUU;
     }
@@ -369,4 +384,20 @@ public class User implements Serializable {
     public void setLock(Integer lock) {
         this.lock = lock;
     }
+
+    public UserRecord getUserRecord() {
+        return userRecord;
+    }
+
+    public void setUserRecord(UserRecord userRecord) {
+        this.userRecord = userRecord;
+    }
+
+    public List<UserQuestion> getQuestions() {
+        return questions;
+    }
+
+    public void setQuestions(List<UserQuestion> questions) {
+        this.questions = questions;
+    }
 }

+ 91 - 0
sso-server/src/main/java/com/uas/sso/entity/UserQuestion.java

@@ -0,0 +1,91 @@
+package com.uas.sso.entity;
+
+import javax.persistence.*;
+import java.io.Serializable;
+
+/**
+ * @author uas
+ * @date 2018/1/10.
+ */
+@Entity
+@Table(name = "sso$user$question")
+public class UserQuestion implements Serializable {
+
+    /**
+     *
+     */
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 主键
+     */
+    @Id
+    @Column(name = "_id")
+    @SequenceGenerator(name = "sso$user$question_gen", sequenceName = "sso$user$question_seq", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "sso$user$question_gen")
+    private Long id;
+
+    /**
+     * 用户uu号
+     */
+    @Column(name = "useruu", insertable=false, updatable=false)
+    private Long userUU;
+
+    /**
+     * 密保问题
+     */
+    @Column(name = "question")
+    private String question;
+
+    /**
+     * 密保答案
+     */
+    @Column(name = "answer")
+    private String answer;
+
+    /**
+     * 排序
+     */
+    @Column(name = "sort")
+    private String sort;
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Long getUserUU() {
+        return userUU;
+    }
+
+    public void setUserUU(Long userUU) {
+        this.userUU = userUU;
+    }
+
+    public String getQuestion() {
+        return question;
+    }
+
+    public void setQuestion(String question) {
+        this.question = question;
+    }
+
+    public String getAnswer() {
+        return answer;
+    }
+
+    public void setAnswer(String answer) {
+        this.answer = answer;
+    }
+
+    public String getSort() {
+        return sort;
+    }
+
+    public void setSort(String sort) {
+        this.sort = sort;
+    }
+}

+ 56 - 0
sso-server/src/main/java/com/uas/sso/entity/UserRecord.java

@@ -0,0 +1,56 @@
+package com.uas.sso.entity;
+
+import javax.persistence.*;
+import java.io.Serializable;
+import java.sql.Timestamp;
+
+/**
+ * 用户登录记录
+ *
+ * @author wangmh
+ * @date 2018/1/9.
+ */
+@Entity
+@Table(name = "sso$user$record")
+public class UserRecord implements Serializable {
+
+    @Id
+    @Column(name = "_id")
+    @SequenceGenerator(name = "sso$user$record_gen", sequenceName = "sso$user$record_seq", allocationSize = 1)
+    @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "sso$user$record_gen")
+    private Long id;
+
+    @Column(name = "last_login_time")
+    private Timestamp lastLoginTime;
+
+    @Column(name = "pwd_error_count", nullable = false)
+    private int pwdErrorCount;
+
+    public UserRecord() {
+        this.pwdErrorCount = 0;
+    }
+
+    public Long getId() {
+        return id;
+    }
+
+    public void setId(Long id) {
+        this.id = id;
+    }
+
+    public Timestamp getLastLoginTime() {
+        return lastLoginTime;
+    }
+
+    public void setLastLoginTime(long lastLoginTime) {
+        this.lastLoginTime = new Timestamp(lastLoginTime);
+    }
+
+    public int getPwdErrorCount() {
+        return pwdErrorCount;
+    }
+
+    public void setPwdErrorCount(int pwdErrorCount) {
+        this.pwdErrorCount = pwdErrorCount;
+    }
+}

+ 19 - 2
sso-server/src/main/java/com/uas/sso/entity/Userspace.java

@@ -61,7 +61,7 @@ public class Userspace implements Serializable {
     /**
      * 营业执照号
      */
-    @Column(name = "business_code")
+    @Column(name = "business_code", unique = true)
     private String businessCode;
 
     /**
@@ -115,7 +115,7 @@ public class Userspace implements Serializable {
     /**
      * 企业信息认证状态
      */
-    @Column(name = "valid_code")
+    @Column(name = "valid_code", nullable = false)
     private Short validCode;
 
     /**
@@ -163,6 +163,15 @@ public class Userspace implements Serializable {
             inverseJoinColumns = {@JoinColumn(name="user_uu", referencedColumnName="useruu")})
     private List<User> users;
 
+    /**
+     * 企业开通的应用
+     */
+    @ManyToMany
+    @JoinTable(name = "sso$app_userspace",
+            joinColumns = {@JoinColumn(name="space_uu", referencedColumnName="spaceuu")},
+            inverseJoinColumns = {@JoinColumn(name="app_uid", referencedColumnName="uid_")})
+    private List<App> apps;
+
     public Userspace() {
     }
 
@@ -349,4 +358,12 @@ public class Userspace implements Serializable {
     public void setUsers(List<User> users) {
         this.users = users;
     }
+
+    public List<App> getApps() {
+        return apps;
+    }
+
+    public void setApps(List<App> apps) {
+        this.apps = apps;
+    }
 }

+ 58 - 0
sso-server/src/main/java/com/uas/sso/filter/SSOInterceptor.java

@@ -0,0 +1,58 @@
+package com.uas.sso.filter;
+
+import com.uas.sso.SSOHelper;
+import com.uas.sso.SSOToken;
+import com.uas.sso.entity.UserAccount;
+import com.uas.sso.support.SystemSession;
+import com.uas.sso.util.FastjsonUtils;
+import com.uas.sso.web.spring.AbstractSSOInterceptor;
+import org.springframework.stereotype.Component;
+import org.springframework.util.StringUtils;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * 登录拦截
+ *
+ * @author wangmh
+ * @date 2018/1/9.
+ */
+@Component
+public class SSOInterceptor extends AbstractSSOInterceptor {
+
+    @Override
+    protected boolean onAuthenticateFailed(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) {
+        return false;
+    }
+
+    @Override
+    protected void onAuthenticateSuccess(HttpServletRequest request, HttpServletResponse response) {
+        UserAccount userAccount = (UserAccount) request.getSession().getAttribute("userAccount");
+        if (userAccount == null) {
+            SSOToken token = SSOHelper.attrToken(request);
+            userAccount = getUserByToken(token);
+            if (userAccount != null) {
+                request.getSession().setAttribute("userAccount", userAccount);
+            }
+        }
+        if (userAccount != null) {
+            SystemSession.setUserAccount(userAccount);
+        }
+    }
+
+    @Override
+    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
+            throws Exception {
+        super.afterCompletion(request, response, handler, ex);
+        SystemSession.clear();
+    }
+
+    private UserAccount getUserByToken(SSOToken token) {
+        UserAccount userAccount = null;
+        if (token != null && !StringUtils.isEmpty(token.getData())) {
+            userAccount = FastjsonUtils.fromJson(token.getData(), UserAccount.class);
+        }
+        return userAccount;
+    }
+}

+ 11 - 0
sso-server/src/main/java/com/uas/sso/profile/Dev.java

@@ -0,0 +1,11 @@
+package com.uas.sso.profile;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * created by shicr on 2017/11/23
+ **/
+@Target({ElementType.TYPE,ElementType.METHOD})
+public @interface Dev {
+}

+ 7 - 0
sso-server/src/main/java/com/uas/sso/profile/Prod.java

@@ -0,0 +1,7 @@
+package com.uas.sso.profile;
+
+/**
+ * created by shicr on 2017/11/23
+ **/
+public @interface Prod {
+}

+ 7 - 0
sso-server/src/main/java/com/uas/sso/profile/Test.java

@@ -0,0 +1,7 @@
+package com.uas.sso.profile;
+
+/**
+ * created by shicr on 2017/11/23
+ **/
+public @interface Test {
+}

+ 17 - 0
sso-server/src/main/java/com/uas/sso/service/ChangeAdminService.java

@@ -0,0 +1,17 @@
+package com.uas.sso.service;
+
+import com.uas.sso.entity.ChangeAdmin;
+
+/**
+ * @author wangmh
+ * @create 2018-01-15 18:32
+ * @desc 更换管理员service
+ **/
+public interface ChangeAdminService {
+
+    /**
+     * 提交申请
+     * @param changeAdmin 更换管理员信息
+     */
+    void submit(ChangeAdmin changeAdmin);
+}

+ 17 - 0
sso-server/src/main/java/com/uas/sso/service/ResetPwdAppealService.java

@@ -0,0 +1,17 @@
+package com.uas.sso.service;
+
+import com.uas.sso.entity.ResetPwdAppeal;
+
+/**
+ * @author wangmh
+ * @create 2018-01-16 13:31
+ * @desc 重置密码申述service
+ **/
+public interface ResetPwdAppealService {
+
+    /**
+     * 提交申述
+     * @param resetPwdAppeal 重置密码申述信息
+     */
+    void submit(ResetPwdAppeal resetPwdAppeal);
+}

+ 86 - 4
sso-server/src/main/java/com/uas/sso/service/UserService.java

@@ -1,9 +1,7 @@
 package com.uas.sso.service;
 
 import com.uas.sso.entity.User;
-import com.uas.sso.entity.UserAccount;
-
-import java.util.List;
+import com.uas.sso.entity.UserRecord;
 
 /**
  * 用户信息service
@@ -40,6 +38,16 @@ public interface UserService {
      */
     boolean mobileHasRegistered(String mobile);
 
+    /**
+     * 判断邮箱是否已经注册
+     *
+     * @param email 邮箱
+     * @return
+     *      true: 已经被注册
+     *      false: 未被注册
+     */
+    boolean emailHasRegistered(String email);
+
     /**
      * 注册新用户
      *
@@ -80,7 +88,7 @@ public interface UserService {
      *
      * @param mobile 登录的手机号
      * @param password 密码
-     * @param isEncry 密码是否加密
+     * @param isEncry password密码是否加密
      */
     void checkPasswordByMobile(String mobile, String password, boolean isEncry);
 
@@ -92,4 +100,78 @@ public interface UserService {
      * @param isEncry 密码是否加密
      */
     void checkPasswordByEmail(String email, String password, boolean isEncry);
+
+    /**
+     * 获得当前账号密码输错次数
+     *
+     * @param username 账号
+     * @return
+     */
+    int getPwdErrorCount(String username);
+
+    /**
+     * 根据用户名找到用户,如果用户名为邮箱,则为已认证邮箱
+     *
+     * @param username
+     * @return
+     */
+    User findByUsername(String username);
+
+    /**
+     * 保存用户登录记录
+     *
+     * @param userRecord
+     */
+    void save(UserRecord userRecord);
+
+    /**
+     * 根据用户uu号查找用户
+     *
+     * @param userUU 用户uu号
+     * @return
+     */
+    User findOne(Long userUU);
+
+    /**
+     * 用户真实姓名是否被认证
+     *
+     * @author wangmh
+     * @date 2018/1/11 14:48
+     * @param realName
+     * @return
+     */
+    boolean realNameIsValid(String realName);
+
+    /**
+     * 身份证号是否被认证
+     *
+     * @author wangmh
+     * @date 2018/1/11 14:56
+     * @param idCard 身份证
+     * @return
+     */
+    boolean idCardIsValid(String idCard);
+
+    /**
+     * 提交身份认证信息
+     *
+     * @author wangmh
+     * @date 2018/1/11 15:15
+     * @param user
+     */
+    void submitIdValidInfo(User user);
+
+    /**
+     * 修改手机号
+     * @param userUU 用户uu号
+     * @param newMobile 新手机号
+     */
+    void updateMobile(Long userUU, String newMobile);
+
+    /**
+     * 修改邮箱
+     * @param userUU 用户uu号
+     * @param newEmail 新邮箱
+     */
+    void updateEmail(Long userUU, String newEmail);
 }

+ 37 - 0
sso-server/src/main/java/com/uas/sso/service/UserspaceService.java

@@ -38,4 +38,41 @@ public interface UserspaceService {
      * @return
      */
     Userspace findByDomain(String domain);
+
+    /**
+     * 校验企业名是否被认证
+     *
+     * @param spaceName 企业名
+     * @return true:认证,false:未认证
+     */
+    boolean spaceNameIsValid(String spaceName);
+
+    /**
+     * 校验营业执照号是否被验证
+     *
+     * @author wangmh
+     * @date 2018/1/11 9:56
+     * @param businessCode 营业执照号
+     * @return true:认证,false:未认证
+     */
+    boolean businessCodeIsValid(String businessCode);
+
+    /**
+     * 认证信息
+     *
+     * @author wangmh
+     * @date 2018/1/11 14:23
+     * @param userspace 企业信息
+     */
+    void submitValidInfo(Userspace userspace);
+
+    /**
+     * 根据企业uu号查找企业信息
+     *
+     * @author wangmh
+     * @date 2018/1/15 13:47
+     * @param spaceUU 企业uu号
+     * @return 企业信息
+     */
+    Userspace findOne(Long spaceUU);
 }

+ 20 - 0
sso-server/src/main/java/com/uas/sso/service/UserspaceValidService.java

@@ -0,0 +1,20 @@
+package com.uas.sso.service;
+
+import com.uas.sso.entity.Userspace;
+
+/**
+ * @author wangmh
+ * @create 2018-01-11 14:06
+ * @desc
+ **/
+public interface UserspaceValidService {
+
+    /**
+     * 提交认证信息
+     *
+     * @author wangmh
+     * @date 2018/1/11 14:09
+     * @param userspace 企业信息
+     */
+    void submitValid(Userspace userspace);
+}

+ 35 - 0
sso-server/src/main/java/com/uas/sso/service/impl/ChangeAdminServiceImpl.java

@@ -0,0 +1,35 @@
+package com.uas.sso.service.impl;
+
+import com.sun.istack.internal.NotNull;
+import com.uas.sso.core.Status;
+import com.uas.sso.dao.ChangeAdminDao;
+import com.uas.sso.entity.ChangeAdmin;
+import com.uas.sso.service.ChangeAdminService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+import java.sql.Timestamp;
+
+/**
+ * @author wangmh
+ * @create 2018-01-15 19:32
+ * @desc
+ **/
+@Service
+public class ChangeAdminServiceImpl implements ChangeAdminService {
+
+    @Autowired
+    private ChangeAdminDao changeAdminDao;
+
+    @Override
+    public void submit(@NotNull ChangeAdmin changeAdmin) {
+        // 设置时间和审核状态
+        if (changeAdmin.getSubmitDate() == null) {
+            changeAdmin.setSubmitDate(new Timestamp(System.currentTimeMillis()));
+        }
+        changeAdmin.setValidCode((short) Status.TO_BE_CERTIFIED.getCode());
+
+        // 保存信息
+        changeAdminDao.save(changeAdmin);
+    }
+}

+ 30 - 0
sso-server/src/main/java/com/uas/sso/service/impl/ResetPwdAppealServiceImpl.java

@@ -0,0 +1,30 @@
+package com.uas.sso.service.impl;
+
+import com.uas.sso.core.Status;
+import com.uas.sso.dao.ResetPwdAppealDao;
+import com.uas.sso.entity.ResetPwdAppeal;
+import com.uas.sso.service.ResetPwdAppealService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author wangmh
+ * @create 2018-01-16 13:33
+ * @desc 重置密码申述service实现
+ **/
+@Service
+public class ResetPwdAppealServiceImpl implements ResetPwdAppealService {
+
+    @Autowired
+    private ResetPwdAppealDao resetPwdAppealDao;
+
+    @Override
+    public void submit(ResetPwdAppeal resetPwdAppeal) {
+        resetPwdAppeal.setAuditDate(null);
+        resetPwdAppeal.setAuditor(null);
+        resetPwdAppeal.setStatus((short) Status.TO_BE_CERTIFIED.getCode());
+
+        // 保存信息
+        resetPwdAppealDao.save(resetPwdAppeal);
+    }
+}

+ 1 - 1
sso-server/src/main/java/com/uas/sso/service/impl/UserAccountService.java

@@ -67,5 +67,5 @@ public interface UserAccountService {
      * @param userUU 用户uu号
      * @return
      */
-    List<UserAccount> findOneByUserUU(String appId, Long userUU);
+    List<UserAccount> findByUserUU(String appId, Long userUU);
 }

+ 1 - 1
sso-server/src/main/java/com/uas/sso/service/impl/UserAccountServiceImpl.java

@@ -45,7 +45,7 @@ public class UserAccountServiceImpl implements UserAccountService {
     }
 
     @Override
-    public List<UserAccount> findOneByUserUU(String appId, Long userUU) {
+    public List<UserAccount> findByUserUU(String appId, Long userUU) {
         return userAccountDao.findByAppIdAndUserUU(appId, userUU);
     }
 }

+ 147 - 0
sso-server/src/main/java/com/uas/sso/service/impl/UserServiceImpl.java

@@ -5,11 +5,18 @@ import com.uas.sso.core.Const;
 import com.uas.sso.core.Status;
 import com.uas.sso.core.Type;
 import com.uas.sso.dao.UserDao;
+import com.uas.sso.dao.UserRecordDao;
 import com.uas.sso.entity.User;
+import com.uas.sso.entity.UserAccount;
+import com.uas.sso.entity.UserRecord;
+import com.uas.sso.entity.Userspace;
 import com.uas.sso.exception.VisibleError;
 import com.uas.sso.logging.LoggerManager;
 import com.uas.sso.logging.UserBufferedLogger;
 import com.uas.sso.service.UserService;
+import com.uas.sso.support.SystemSession;
+import com.uas.sso.util.AccountTypeUtils;
+import com.uas.sso.util.BeanUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.util.CollectionUtils;
@@ -32,6 +39,9 @@ public class UserServiceImpl implements UserService {
     @Autowired
     private UserDao userDao;
 
+    @Autowired
+    private UserRecordDao userRecordDao;
+
     private UserBufferedLogger userLog = LoggerManager.getLogger(UserBufferedLogger.class);
 
     @Override
@@ -53,6 +63,15 @@ public class UserServiceImpl implements UserService {
         return true;
     }
 
+    @Override
+    public boolean emailHasRegistered(String email) {
+        List<User> users = userDao.findByEmailAndEmailValidCode(email, (short) Status.AUTHENTICATED.getCode());
+        if (CollectionUtils.isEmpty(users)) {
+            return false;
+        }
+        return true;
+    }
+
     @Override
     public User register(User user) {
         // 校验手机号是否被注册
@@ -74,6 +93,7 @@ public class UserServiceImpl implements UserService {
         user.setEmailValidCode((short) Status.NOT_APPLYING.getCode());
         user.setIdentityValidCode((short) Status.NOT_APPLYING.getCode());
         user.setPassword(getEncryPassword(Const.ENCRY_FORMAT, user.getPassword(), user.getSalt()));
+        user.setUserRecord(new UserRecord());
 
         userDao.save(user);
         userLog.info(user, Type.UPDATE_REGISTER.getValue());
@@ -141,6 +161,39 @@ public class UserServiceImpl implements UserService {
         }
     }
 
+    @Override
+    public int getPwdErrorCount(String username) {
+        User user = findByUsername(username);
+        if (user == null) {
+            throw new VisibleError("用户名不存在");
+        }
+        if (user.getUserRecord() == null) {
+            return 0;
+        }
+        return user.getUserRecord().getPwdErrorCount();
+    }
+
+    @Override
+    public User findByUsername(String username) {
+        String type = AccountTypeUtils.getAccountType(username);
+        User user = null;
+        if (AccountTypeUtils.MOBILE.equals(type)) {
+            // 手机号
+            user = userDao.findByMobile(username);
+        } else if (AccountTypeUtils.EMAIL.equals(type)) {
+            // 邮箱
+            List<User> users = userDao.findByEmailAndEmailValidCode(username, (short) Status.AUTHENTICATED.getCode());
+            // 认证邮箱只有一条记录,直接选择第一个
+            if (!CollectionUtils.isEmpty(users)) {
+                user = users.get(0);
+            }
+        } else if (AccountTypeUtils.UU_NUMBER.equals(type)) {
+            // uu号
+            user = userDao.findByUserUU(Long.valueOf(type));
+        }
+        return user;
+    }
+
     /**
      * 校验用户密码
      *
@@ -160,4 +213,98 @@ public class UserServiceImpl implements UserService {
             throw new VisibleError("密码不一致");
         }
     }
+
+    @Override
+    public void save(UserRecord userRecord) {
+        userRecordDao.save(userRecord);
+    }
+
+    @Override
+    public User findOne(Long userUU) {
+        return userDao.findOne(userUU);
+    }
+
+    @Override
+    public boolean realNameIsValid(String realName) {
+        User user = userDao.findByRealName(realName);
+        if (user != null && user.getIdentityValidCode() == Status.AUTHENTICATED.getCode()) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public boolean idCardIsValid(String idCard) {
+        User user = userDao.findByIdCard(idCard);
+        if (user != null && user.getIdentityValidCode() == Status.AUTHENTICATED.getCode()) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void submitIdValidInfo(User user) {
+        // 校验企业名和营业执照是否被认证
+        boolean isValid = realNameIsValid(user.getRealName());
+        if (isValid) {
+            throw new VisibleError("该真实姓名已被认证,请确认");
+        }
+        isValid = idCardIsValid(user.getIdCard());
+        if (isValid) {
+            throw new VisibleError("该身份证号已被认证,请确认");
+        }
+
+        // 根据登录信息找到用户
+        UserAccount userAccount = SystemSession.getUserAccount();
+        User oldUser = userDao.findOne(userAccount.getUserUU());
+
+        // 将数据拷贝到原用户中
+        BeanUtil.copyProperties(user, oldUser, true);
+
+        // 设置用户真实身份未待认证状态
+        oldUser.setIdentityValidCode((short) Status.TO_BE_CERTIFIED.getCode());
+
+        // 保存用户信息
+        userDao.save(oldUser);
+
+        // TODO 保存日志
+    }
+
+    @Override
+    public void updateMobile(Long userUU, String newMobile) {
+        // 获取用户信息
+        User user = userDao.findOne(userUU);
+        if (user == null) {
+            throw new VisibleError("用户不存在");
+        }
+
+        // 修改手机号
+        user.setMobile(newMobile);
+        user.setMobileValidCode((short) Status.AUTHENTICATED.getCode());
+
+        // 保存用户信息
+        userDao.save(user);
+
+        // 保存日志
+        userLog.info(user, Type.UPDATE_MOBILE.getValue());
+    }
+
+    @Override
+    public void updateEmail(Long userUU, String newEmail) {
+        // 获取用户信息
+        User user = userDao.findOne(userUU);
+        if (user == null) {
+            throw new VisibleError("用户不存在");
+        }
+
+        // 修改手机号
+        user.setEmail(newEmail);
+        user.setEmailValidCode((short) Status.AUTHENTICATED.getCode());
+
+        // 保存用户信息
+        userDao.save(user);
+
+        // 保存日志
+        userLog.info(user, Type.UPDATE_EMAIL.getValue());
+    }
 }

+ 54 - 0
sso-server/src/main/java/com/uas/sso/service/impl/UserspaceServiceImpl.java

@@ -1,11 +1,13 @@
 package com.uas.sso.service.impl;
 
+import com.uas.sso.core.Status;
 import com.uas.sso.dao.UserspaceDao;
 import com.uas.sso.entity.User;
 import com.uas.sso.entity.Userspace;
 import com.uas.sso.exception.VisibleError;
 import com.uas.sso.service.UserService;
 import com.uas.sso.service.UserspaceService;
+import com.uas.sso.util.BeanUtil;
 import com.uas.sso.util.ChineseUtils;
 import com.uas.sso.util.StringUtil;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -130,4 +132,56 @@ public class UserspaceServiceImpl implements UserspaceService {
     public Userspace findByDomain(String domain) {
         return userspaceDao.findByDomain(domain);
     }
+
+    @Override
+    public boolean spaceNameIsValid(String spaceName) {
+        Userspace userspace = userspaceDao.findBySpaceName(spaceName);
+        if (userspace == null) {
+            throw new VisibleError("该企业未注册");
+        }
+        return userspace.getValidCode() == Status.AUTHENTICATED.getCode();
+    }
+
+    @Override
+    public boolean businessCodeIsValid(String businessCode) {
+        Userspace userspace = userspaceDao.findByBusinessCode(businessCode);
+        // 营业执照不是注册必填项
+        if (userspace != null && userspace.getValidCode() == Status.AUTHENTICATED.getCode()) {
+            return true;
+        }
+        return false;
+    }
+
+    @Override
+    public void submitValidInfo(Userspace userspace) {
+        // 校验企业名和营业执照是否被认证
+        boolean isValid = spaceNameIsValid(userspace.getSpaceName());
+        if (isValid) {
+            throw new VisibleError("该企业名已被认证,请确认");
+        }
+        isValid = businessCodeIsValid(userspace.getBusinessCode());
+        if (isValid) {
+            throw new VisibleError("该企业营业执照号已被认证,请确认");
+        }
+
+        // 根据企业名找到原企业信息
+        Userspace oldUserspace = userspaceDao.findBySpaceName(userspace.getSpaceName());
+
+        // 将数据拷贝到原企业中
+        BeanUtil.copyProperties(userspace, oldUserspace, true);
+
+        // 设置企业未待认证状态
+        oldUserspace.setValidCode((short) Status.TO_BE_CERTIFIED.getCode());
+
+        // 保存企业信息
+        userspaceDao.save(oldUserspace);
+
+        // TODO 保存日志
+
+    }
+
+    @Override
+    public Userspace findOne(Long spaceUU) {
+        return userspaceDao.findOne(spaceUU);
+    }
 }

+ 19 - 0
sso-server/src/main/java/com/uas/sso/service/impl/UserspaceValidServiceImpl.java

@@ -0,0 +1,19 @@
+package com.uas.sso.service.impl;
+
+import com.uas.sso.entity.Userspace;
+import com.uas.sso.service.UserspaceValidService;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author wangmh
+ * @create 2018-01-11 14:10
+ * @desc 企业信息认证service实现
+ **/
+@Service
+public class UserspaceValidServiceImpl implements UserspaceValidService {
+
+
+    @Override
+    public void submitValid(Userspace userspace) {
+    }
+}

+ 28 - 0
sso-server/src/main/java/com/uas/sso/support/SystemSession.java

@@ -0,0 +1,28 @@
+/**
+ * Company usoftchina
+ * Copyright (C) 2004-2017 All Rights Reserved.
+ */
+package com.uas.sso.support;
+
+import com.uas.sso.entity.UserAccount;
+
+/**
+ * @author wangmh
+ * @date 2018/1/9
+ */
+public class SystemSession {
+
+    private static ThreadLocal<UserAccount> local = new ThreadLocal<UserAccount>();
+
+    public static UserAccount getUserAccount() {
+        return local.get();
+    }
+
+    public static void setUserAccount(UserAccount userAccount) {
+        SystemSession.local.set(userAccount);
+    }
+
+    public static void clear() {
+        local.set(null);
+    }
+}

+ 29 - 0
sso-server/src/main/java/com/uas/sso/timertask/UserLockTimerTask.java

@@ -0,0 +1,29 @@
+package com.uas.sso.timertask;
+
+import com.uas.sso.dao.UserRecordDao;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.scheduling.annotation.Scheduled;
+import org.springframework.stereotype.Component;
+
+/**
+ * 用户账户锁定定时任务
+ *
+ * @author wangmh
+ */
+@Component
+public class UserLockTimerTask {
+
+    @Autowired
+    private UserRecordDao userRecordDao;
+
+    @Scheduled(cron = "0 0 0 * * *")
+    public void deleteAllLock() {
+        try {
+            userRecordDao.clearPwdErrorCount();
+            System.out.println("锁定清除:"+System.currentTimeMillis());
+        } catch (Exception e) {
+
+        }
+    }
+
+}

+ 105 - 0
sso-server/src/main/java/com/uas/sso/util/CaptchaUtil.java

@@ -0,0 +1,105 @@
+package com.uas.sso.util;
+
+import com.sun.image.codec.jpeg.JPEGCodec;
+import com.sun.image.codec.jpeg.JPEGImageEncoder;
+
+import javax.servlet.ServletException;
+import javax.servlet.ServletOutputStream;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.awt.*;
+import java.awt.image.BufferedImage;
+import java.io.IOException;
+import java.util.Random;
+
+/**
+ * 图片验证码工具类
+ *
+ * @author wangmh
+ * @date 2017/11/2
+ */
+public class CaptchaUtil {
+
+    private CaptchaUtil(){}
+
+    /**
+     * 随机字符字典
+     */
+    private static final char[] CHARS = { '2', '3', '4', '5', '6', '7', '8',
+            '9', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'J', 'K', 'L', 'M',
+            'N', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z' };
+
+    /**
+     * 随机数
+     */
+    private static Random random = new Random();
+
+    /**
+     * 获取6位随机数
+     */
+    private static String getRandomString()
+    {
+        StringBuffer buffer = new StringBuffer();
+        for(int i = 0; i < 4; i++)
+        {
+            buffer.append(CHARS[random.nextInt(CHARS.length)]);
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * 获取随机数颜色
+     */
+    private static Color getRandomColor()
+    {
+        return new Color(255,255,255);
+    }
+
+    /**
+     * 返回某颜色的反色
+     */
+    private static Color getReverseColor(Color c)
+    {
+        return new Color(255 - c.getRed(), 255 - c.getGreen(),
+                255 - c.getBlue());
+    }
+
+    /**
+     *
+     * @param request
+     * @param response
+     * @param key 放到session中的key值
+     * @throws ServletException
+     * @throws IOException
+     */
+    public static void outputCaptcha(HttpServletRequest request, HttpServletResponse response, String key)
+            throws ServletException, IOException
+    {
+
+        response.setContentType("image/jpeg");
+
+        String randomString = getRandomString();
+        request.getSession(true).setAttribute(key, randomString);
+
+        int width = 100;
+        int height = 30;
+
+        Color color = getRandomColor();
+        Color reverse = getReverseColor(color);
+
+        BufferedImage bi = new BufferedImage(width, height,
+                BufferedImage.TYPE_INT_RGB);
+        Graphics2D g = bi.createGraphics();
+        g.setFont(new Font(Font.SANS_SERIF, Font.ROMAN_BASELINE, 18));
+        g.setColor(color);
+        g.fillRect(0, 0, width, height);
+        g.setColor(reverse);
+        g.drawString(randomString, 18, 20);
+
+        // 转成JPEG格式
+        ServletOutputStream out = response.getOutputStream();
+        JPEGImageEncoder encoder = JPEGCodec.createJPEGEncoder(out);
+        encoder.encode(bi);
+        out.flush();
+    }
+}

+ 93 - 0
sso-server/src/main/java/com/uas/sso/util/FastjsonUtils.java

@@ -0,0 +1,93 @@
+package com.uas.sso.util;
+
+import com.alibaba.fastjson.JSON;
+import com.alibaba.fastjson.JSONArray;
+import com.alibaba.fastjson.JSONObject;
+import com.alibaba.fastjson.parser.Feature;
+import com.alibaba.fastjson.serializer.SerializerFeature;
+
+import java.util.List;
+
+/**
+ * @author yingp
+ * @see JSON
+ *
+ */
+public class FastjsonUtils {
+
+	public static Feature DEFAULT_PARSER_FEATURE = Feature.DisableCircularReferenceDetect;
+	public static SerializerFeature DEFAULT_SERIAL_FEATURE = SerializerFeature.DisableCircularReferenceDetect;
+
+	/**
+	 * 把JSON文本parse为JSONObject或者JSONArray
+	 * 
+	 * @param text
+	 * @return
+	 */
+	public static Object parse(String text) {
+		return JSON.parse(text, DEFAULT_PARSER_FEATURE);
+	}
+
+	/**
+	 * 把JSON文本parse成JSONObject
+	 * 
+	 * @param text
+	 * @return
+	 */
+	public static final JSONObject parseObject(String text) {
+		return JSON.parseObject(text, DEFAULT_PARSER_FEATURE);
+	}
+
+	/**
+	 * 把JSON文本parse为JavaBean
+	 * 
+	 * @param text
+	 * @param clazz
+	 * @return
+	 */
+	public static final <T> T fromJson(String text, Class<T> clazz) {
+		return JSON.parseObject(text, clazz, DEFAULT_PARSER_FEATURE);
+	}
+
+	/**
+	 * 把JSON文本parse成JSONArray
+	 * 
+	 * @param text
+	 * @return
+	 */
+	public static final JSONArray fromJsonArray(String text) {
+		return JSON.parseArray(text);
+	}
+
+	/**
+	 * 把JSON文本parse成JavaBean集合
+	 * 
+	 * @param text
+	 * @param clazz
+	 * @return
+	 */
+	public static final <T> List<T> fromJsonArray(String text, Class<T> clazz) {
+		return JSON.parseArray(text, clazz);
+	}
+
+	/**
+	 * 将JavaBean序列化为JSON文本
+	 * 
+	 * @param object
+	 * @return
+	 */
+	public static final String toJson(Object object) {
+		return JSON.toJSONString(object, DEFAULT_SERIAL_FEATURE);
+	}
+
+	/**
+	 * 将JavaBean转换为JSONObject或者JSONArray。
+	 * 
+	 * @param javaObject
+	 * @return
+	 */
+	public static final Object toJSON(Object javaObject) {
+		return JSON.toJSON(javaObject);
+	}
+
+}

+ 35 - 0
sso-server/src/main/java/com/uas/sso/util/FileUrl.java

@@ -0,0 +1,35 @@
+package com.uas.sso.util;
+
+/**
+ * 文件服务器的基本链接
+ *
+ * @author yuj 2017-10-12 14:53
+ */
+public class FileUrl {
+
+    /**
+     * 文件上传
+     */
+    public final static String FILE_UPLOAD = "http://10.10.100.200:9999/file/upload";
+
+
+    /**
+     * 文件下载
+     */
+    public final static String FILE_DOWNLOAD = "http://10.10.100.200:9999/file/download";
+
+    /**
+     * 文件删除
+     */
+    public final static String FILE_DELETE = "http://10.10.100.200:9999/file/delete";
+
+    /**
+     * 文件信息
+     */
+    public final static String FILE_INFO = "http://10.10.100.200:9999/file/info";
+
+    /**
+     * 文件额外属性
+     */
+    public final static String FILE_METADATA = "http://10.10.100.200:9999/file/metadata";
+}

+ 306 - 0
sso-server/src/main/java/com/uas/sso/util/HttpUtils.java

@@ -0,0 +1,306 @@
+package com.uas.sso.util;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.http.Consts;
+import org.apache.http.HttpEntity;
+import org.apache.http.HttpResponse;
+import org.apache.http.NameValuePair;
+import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.entity.UrlEncodedFormEntity;
+import org.apache.http.client.methods.CloseableHttpResponse;
+import org.apache.http.client.methods.HttpEntityEnclosingRequestBase;
+import org.apache.http.client.methods.HttpGet;
+import org.apache.http.client.methods.HttpPost;
+import org.apache.http.entity.ContentType;
+import org.apache.http.entity.StringEntity;
+import org.apache.http.entity.mime.MultipartEntityBuilder;
+import org.apache.http.entity.mime.content.FileBody;
+import org.apache.http.entity.mime.content.InputStreamBody;
+import org.apache.http.entity.mime.content.StringBody;
+import org.apache.http.impl.client.CloseableHttpClient;
+import org.apache.http.impl.client.HttpClients;
+import org.apache.http.message.BasicNameValuePair;
+import org.springframework.web.multipart.MultipartFile;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URLEncoder;
+import java.util.*;
+import java.util.Map.Entry;
+
+
+/**
+ * 旧版账户中心拷贝
+ *
+ * @author wangmh
+ */
+public class HttpUtils {
+
+	/**
+	 * 发起POST、PUT请求
+	 * 
+	 * @param params
+	 * @return
+	 * @throws Exception
+	 */
+	public static Response get(String url, Map<String, Object> params) throws Exception {
+		CloseableHttpClient httpClient = HttpClients.createDefault();
+		HttpEntityEnclosingRequestBase request = null;
+		CloseableHttpResponse response = null;
+		try {
+			StringBuilder buf = new StringBuilder(url);
+			if (params != null && !params.isEmpty()) {
+				if (url.indexOf("?") == -1) {
+					buf.append("?");
+				} else if (!url.endsWith("&")) {
+					buf.append("&");
+				}
+				Set<Entry<String, Object>> entrys = params.entrySet();
+				for (Entry<String, Object> entry : entrys) {
+					buf.append(entry.getKey()).append("=").append(URLEncoder.encode(String.valueOf(entry.getValue()), "UTF-8")).append("&");
+				}
+			}
+			request = new HttpPost(buf.toString());
+			response = httpClient.execute(request);
+			return Response.getResponse(response);
+		} finally {
+			request.releaseConnection();
+			try {
+				httpClient.close();
+			} catch (IOException e) {
+			}
+			if (response != null) {
+				try {
+					response.close();
+				} catch (IOException e) {
+				}
+			}
+		}
+	}
+
+	/**
+	 * 发起POST、PUT请求
+	 *
+	 * @param datas
+	 * @return
+	 * @throws Exception
+	 */
+	public static Response post(String url, Collection<?> datas) throws Exception {
+		CloseableHttpClient httpClient = HttpClients.createDefault();
+		HttpEntityEnclosingRequestBase request = new HttpPost(url);
+		CloseableHttpResponse response = null;
+		try {
+			if (datas != null && !datas.isEmpty()) {
+				request.setEntity(new StringEntity(FastjsonUtils.toJson(datas), ContentType.create("text/plain", Consts.UTF_8)));
+			}
+			response = httpClient.execute(request);
+			return Response.getResponse(response);
+		} finally {
+			request.releaseConnection();
+			try {
+				httpClient.close();
+			} catch (IOException e) {
+			}
+			if (response != null) {
+				try {
+					response.close();
+				} catch (IOException e) {
+				}
+			}
+		}
+	}
+
+	/**
+	 * 发起POST、PUT请求
+	 *
+	 * @param params
+	 * @return
+	 * @throws Exception
+	 */
+	public static Response post(String url, Map<String, String> params) throws Exception {
+		CloseableHttpClient httpClient = HttpClients.createDefault();
+		HttpEntityEnclosingRequestBase request = new HttpPost(url);
+		CloseableHttpResponse response = null;
+		try {
+			List<NameValuePair> nvps = new ArrayList<NameValuePair>();
+			if (params != null && !params.isEmpty()) {
+				Set<Entry<String, String>> entrys = params.entrySet();
+				for (Entry<String, String> entry : entrys) {
+					nvps.add(new BasicNameValuePair(entry.getKey(), URLEncoder.encode(entry.getValue(), "UTF-8")));
+				}
+			}
+			request.setEntity(new UrlEncodedFormEntity(nvps));
+			response = httpClient.execute(request);
+			return Response.getResponse(response);
+		} finally {
+			request.releaseConnection();
+			try {
+				httpClient.close();
+			} catch (IOException e) {
+			}
+			if (response != null) {
+				try {
+					response.close();
+				} catch (IOException e) {
+				}
+			}
+		}
+	}
+
+	/**
+	 * http上传文件
+	 * 
+	 * @param url
+	 *            请求地址
+	 * @param filePath
+	 *            附件路径
+	 * @param params
+	 *            参数
+	 * @return
+	 * @throws Exception
+	 * @throws IOException
+	 * @throws IllegalStateException
+	 */
+	public static Response upload(String url, String filePath, Map<String, String> params) throws IllegalStateException, IOException,
+			Exception {
+		CloseableHttpClient httpClient = null;
+		CloseableHttpResponse response = null;
+		try {
+			httpClient = HttpClients.createDefault();
+			HttpPost httpPost = new HttpPost(url);
+			FileBody fileBody = new FileBody(new File(filePath));
+			MultipartEntityBuilder builder = MultipartEntityBuilder.create();
+			builder.addPart("file", fileBody);
+			if (params != null) {
+				for (String paramKey : params.keySet()) {
+					StringBody body = new StringBody(params.get(paramKey), ContentType.create("text/plain", Consts.UTF_8));
+					builder.addPart(paramKey, body);
+				}
+			}
+			HttpEntity reqEntity = builder.build();
+			httpPost.setEntity(reqEntity);
+			response = httpClient.execute(httpPost);
+			return Response.getResponse(response);
+		} finally {
+			try {
+				if (response != null) {
+					response.close();
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			try {
+				if (httpClient != null) {
+					httpClient.close();
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	/**
+	 * http上传文件
+	 *
+	 * @param url
+	 *            请求地址
+	 * @param multipartFile
+	 *            附件路径
+	 * @param params
+	 *            参数
+	 * @return
+	 * @throws Exception
+	 * @throws IOException
+	 * @throws IllegalStateException
+	 */
+	public static Response upload(String url, MultipartFile multipartFile, Map<String, String> params) throws IllegalStateException, IOException,
+			Exception {
+		CloseableHttpClient httpClient = null;
+		CloseableHttpResponse response = null;
+		try {
+			httpClient = HttpClients.createDefault();
+			HttpPost httpPost = new HttpPost(url);
+			InputStreamBody streamBody = new InputStreamBody(multipartFile.getInputStream(),
+				multipartFile.getOriginalFilename());
+			MultipartEntityBuilder builder = MultipartEntityBuilder.create();
+			builder.addPart("file", streamBody);
+			if (params != null) {
+				for (String paramKey : params.keySet()) {
+					StringBody body = new StringBody(params.get(paramKey), ContentType.create("text/plain", Consts.UTF_8));
+					builder.addPart(paramKey, body);
+				}
+			}
+			HttpEntity reqEntity = builder.build();
+			httpPost.setEntity(reqEntity);
+			response = httpClient.execute(httpPost);
+			return Response.getResponse(response);
+		} finally {
+			try {
+				if (response != null) {
+					response.close();
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+			try {
+				if (httpClient != null) {
+					httpClient.close();
+				}
+			} catch (IOException e) {
+				e.printStackTrace();
+			}
+		}
+	}
+
+	/**
+	 * 下载
+	 * 
+	 * @param url
+	 * @return
+	 * @throws ClientProtocolException
+	 * @throws IOException
+	 */
+	public static InputStream download(String url) throws ClientProtocolException, IOException {
+		CloseableHttpClient httpClient = HttpClients.createDefault();
+		HttpGet httpGet = new HttpGet(url);
+		CloseableHttpResponse response = httpClient.execute(httpGet);
+		return response.getEntity().getContent();
+	}
+
+	public static class Response {
+		private int statusCode;
+		private String responseText;
+
+		public int getStatusCode() {
+			return statusCode;
+		}
+
+		public void setStatusCode(int statusCode) {
+			this.statusCode = statusCode;
+		}
+
+		public String getResponseText() {
+			return responseText;
+		}
+
+		public void setResponseText(String responseText) {
+			this.responseText = responseText;
+		}
+
+		public Response() {
+		}
+
+		public Response(HttpResponse response) throws IllegalStateException, IOException, Exception {
+			this.statusCode = response.getStatusLine().getStatusCode();
+			this.responseText = IOUtils.toString(response.getEntity().getContent());
+		}
+
+		public static Response getResponse(HttpResponse response) throws IllegalStateException, IOException, Exception {
+			if (response != null) {
+				return new Response(response);
+			}
+			return null;
+		}
+	}
+}

+ 33 - 0
sso-server/src/main/java/com/uas/sso/util/ParameterUtils.java

@@ -0,0 +1,33 @@
+package com.uas.sso.util;
+
+import com.uas.sso.exception.VisibleError;
+
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * @author wangmh
+ * @create 2018-01-11 10:46
+ * @desc 参数工具类
+ **/
+public class ParameterUtils {
+
+    /**
+     * 校验空参数
+     *
+     * @author wangmh
+     * @date 2018/1/11 10:47
+     * @param params 参数,key为参数名,value为参数
+     *
+     */
+    public static void checkEmptyParameter(Map<String, String> params) {
+        Set<Map.Entry<String, String>> entries = params.entrySet();
+        for (Map.Entry<String, String> entry : entries) {
+            String key = entry.getKey();
+            String value = entry.getValue();
+            if (StringUtils.isEmpty(value)) {
+                throw new VisibleError(key + "不能为空");
+            }
+        }
+    }
+}

+ 12 - 0
sso-server/src/main/resources/dev/account.properties

@@ -0,0 +1,12 @@
+### sso config
+sso.app=sso
+# token secretkey
+sso.secretkey=0taQcW073Z7G628g5H
+#sso.cookie.domain=ubtob.com
+sso.cookie.secure=false
+sso.login.url=/sso/login
+
+### crossdomain verify
+sso.authcookie.secretkey=Z318866alN6gA0piuO
+sso.center.public_key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL2g7CEfuPZtEDy7Iz5AL6iwbHZewWGUBYUWxKnFAwAW4lY8mMavn5Ke5mB25eKj5bvUsB48r8gWTvJNsKRGEw8CAwEAAQ==
+sso.center.private_key=MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvaDsIR+49m0QPLsjPkAvqLBsdl7BYZQFhRbEqcUDABbiVjyYxq+fkp7mYHbl4qPlu9SwHjyvyBZO8k2wpEYTDwIDAQABAj9Ts7SG6nm6TGneZLwpvitLSpSVqz2w1KWbGXG1fkDUyIJbNbyLmFTNAlfAgM4eC3EzVHVC3FrC+5sl4Fwn2PECIQDn9zz0xFmSQt8csMhu7jyh4UNDA3P11C9AkzaLykYNtwIhANFGtu9TJH2wZNfSA0qBNCgcyJJHXx59VTtih0R+6SVpAiEAmknpwoiDZ3SRQF0ZxCc0LxxNB9rZG475qwMACfUNqXsCIQCWLpAjSWA7jrWfp8fS1MvQKW/KgcuB/uGGf1uhTQ4VWQIhAJ6xJuj+eJAV2gsRDDjNSkD+Jm4qNaZ5ec/XnM7w2YcZ

+ 12 - 0
sso-server/src/main/resources/prod/account.properties

@@ -0,0 +1,12 @@
+### sso config
+sso.app=sso
+# token secretkey
+sso.secretkey=0taQcW073Z7G628g5H
+sso.cookie.domain=ubtob.com
+sso.cookie.secure=false
+sso.login.url=/sso/login
+
+### crossdomain verify
+sso.authcookie.secretkey=Z318866alN6gA0piuO
+sso.center.public_key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL2g7CEfuPZtEDy7Iz5AL6iwbHZewWGUBYUWxKnFAwAW4lY8mMavn5Ke5mB25eKj5bvUsB48r8gWTvJNsKRGEw8CAwEAAQ==
+sso.center.private_key=MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvaDsIR+49m0QPLsjPkAvqLBsdl7BYZQFhRbEqcUDABbiVjyYxq+fkp7mYHbl4qPlu9SwHjyvyBZO8k2wpEYTDwIDAQABAj9Ts7SG6nm6TGneZLwpvitLSpSVqz2w1KWbGXG1fkDUyIJbNbyLmFTNAlfAgM4eC3EzVHVC3FrC+5sl4Fwn2PECIQDn9zz0xFmSQt8csMhu7jyh4UNDA3P11C9AkzaLykYNtwIhANFGtu9TJH2wZNfSA0qBNCgcyJJHXx59VTtih0R+6SVpAiEAmknpwoiDZ3SRQF0ZxCc0LxxNB9rZG475qwMACfUNqXsCIQCWLpAjSWA7jrWfp8fS1MvQKW/KgcuB/uGGf1uhTQ4VWQIhAJ6xJuj+eJAV2gsRDDjNSkD+Jm4qNaZ5ec/XnM7w2YcZ

+ 12 - 0
sso-server/src/main/resources/test/account.properties

@@ -0,0 +1,12 @@
+### sso config
+sso.app=sso
+# token secretkey
+sso.secretkey=0taQcW073Z7G628g5H
+#sso.cookie.domain=ubtob.com
+sso.cookie.secure=false
+sso.login.url=/sso/login
+
+### crossdomain verify
+sso.authcookie.secretkey=Z318866alN6gA0piuO
+sso.center.public_key=MFwwDQYJKoZIhvcNAQEBBQADSwAwSAJBAL2g7CEfuPZtEDy7Iz5AL6iwbHZewWGUBYUWxKnFAwAW4lY8mMavn5Ke5mB25eKj5bvUsB48r8gWTvJNsKRGEw8CAwEAAQ==
+sso.center.private_key=MIIBVQIBADANBgkqhkiG9w0BAQEFAASCAT8wggE7AgEAAkEAvaDsIR+49m0QPLsjPkAvqLBsdl7BYZQFhRbEqcUDABbiVjyYxq+fkp7mYHbl4qPlu9SwHjyvyBZO8k2wpEYTDwIDAQABAj9Ts7SG6nm6TGneZLwpvitLSpSVqz2w1KWbGXG1fkDUyIJbNbyLmFTNAlfAgM4eC3EzVHVC3FrC+5sl4Fwn2PECIQDn9zz0xFmSQt8csMhu7jyh4UNDA3P11C9AkzaLykYNtwIhANFGtu9TJH2wZNfSA0qBNCgcyJJHXx59VTtih0R+6SVpAiEAmknpwoiDZ3SRQF0ZxCc0LxxNB9rZG475qwMACfUNqXsCIQCWLpAjSWA7jrWfp8fS1MvQKW/KgcuB/uGGf1uhTQ4VWQIhAJ6xJuj+eJAV2gsRDDjNSkD+Jm4qNaZ5ec/XnM7w2YcZ