Browse Source

登录密码错误次数修改成Redis

wangmh 7 years ago
parent
commit
fe1a3133e0

+ 1 - 0
sso-manage-console/build.gradle

@@ -29,6 +29,7 @@ dependencies {
   compile("org.springframework.boot:spring-boot-starter-data-jpa")
   compile("org.springframework.boot:spring-boot-starter-actuator")
   compile("org.springframework.boot:spring-boot-starter-mail")
+  compile("org.springframework.boot:spring-boot-starter-data-redis")
   compile("net.sourceforge.nekohtml:nekohtml:1.9.15")
 
   compile('commons-codec:commons-codec:1.11')

+ 2 - 1
sso-manage-console/src/main/java/com/uas/sso/sso/backend/api/UserManageController.java

@@ -105,6 +105,7 @@ public class UserManageController {
     @RequestMapping(method = RequestMethod.POST, path = "//resetPwdCount",
             produces = MediaType.APPLICATION_JSON_UTF8_VALUE)
     public ResultBean<UserRecord> resetPwdCount(@RequestParam("userUU") Long userUU) {
-        return new ResultBean<>(userBackendService.resetErrorCount(userUU));
+        userBackendService.resetErrorCount(userUU);
+        return new ResultBean<>(new UserRecord());
     }
 }

+ 31 - 0
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/TokenService.java

@@ -0,0 +1,31 @@
+package com.uas.sso.sso.backend.service;
+
+import com.uas.sso.entity.Token;
+
+/**
+ * token service
+ *
+ * @author wangmh
+ * @date 2018/1/3
+ */
+public interface TokenService {
+
+    /**
+     * 保存token
+     * @param token
+     */
+    void save(Token token);
+
+    /**
+     * 根据token id 找到token
+     * @param tokenId tokenId
+     * @return token
+     */
+    Token findOne(String tokenId);
+
+    /**
+     * 删除token
+     * @param tokenId tokenId
+     */
+    void delete(String tokenId);
+}

+ 1 - 1
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/UserBackendService.java

@@ -86,6 +86,6 @@ public interface UserBackendService {
 
     User authUserValid(Long userUU, Long validId, Boolean isPass, String reason);
 
-    UserRecord resetErrorCount(Long userUU);
+    void resetErrorCount(Long userUU);
 }
 

+ 40 - 0
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/impl/TokenServiceImpl.java

@@ -0,0 +1,40 @@
+package com.uas.sso.sso.backend.service.impl;
+
+import com.uas.sso.entity.Token;
+import com.uas.sso.sso.backend.service.TokenService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.redis.core.RedisTemplate;
+import org.springframework.stereotype.Service;
+
+import java.util.concurrent.TimeUnit;
+
+/**
+ * token service实现
+ *
+ * @author wangmh
+ * @date 2018/1/3
+ */
+@Service
+public class TokenServiceImpl implements TokenService {
+
+    @Autowired
+    private RedisTemplate redisTemplate;
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void save(Token token) {
+        redisTemplate.opsForValue().set(token.getId(), token, token.getExpires_in(), TimeUnit.SECONDS);
+    }
+
+    @Override
+    public Token findOne(String tokenId) {
+        Token token = (Token) redisTemplate.opsForValue().get(tokenId);
+        return token;
+    }
+
+    @SuppressWarnings("unchecked")
+    @Override
+    public void delete(String tokenId) {
+        redisTemplate.delete(tokenId);
+    }
+}

+ 7 - 8
sso-manage-console/src/main/java/com/uas/sso/sso/backend/service/impl/UserBackendServiceImpl.java

@@ -18,6 +18,7 @@ import com.uas.sso.sso.backend.config.SyncThreadPool.BackInfoType;
 import com.uas.sso.sso.backend.dto.AddNewUserInfo;
 import com.uas.sso.sso.backend.dto.UpdateUserInfo;
 import com.uas.sso.sso.backend.exceptions.ValidationFailedException;
+import com.uas.sso.sso.backend.service.TokenService;
 import com.uas.sso.sso.backend.service.UserBackendService;
 import com.uas.sso.sso.backend.util.JacksonUtils;
 import com.uas.sso.util.InfoAsyncUtils;
@@ -60,13 +61,16 @@ public class UserBackendServiceImpl implements UserBackendService {
 
     private final SyncThreadPool syncThreadPool;
 
+    private final TokenService tokenService;
+
     @Autowired
-    public UserBackendServiceImpl(AppDao appDao, UserDao userDao, UserValidDao userValidDao, UserRecordDao userRecordDao, SyncThreadPool syncThreadPool) {
+    public UserBackendServiceImpl(AppDao appDao, UserDao userDao, UserValidDao userValidDao, UserRecordDao userRecordDao, SyncThreadPool syncThreadPool, TokenService tokenService) {
         this.appDao = appDao;
         this.userDao = userDao;
         this.userValidDao = userValidDao;
         this.userRecordDao = userRecordDao;
         this.syncThreadPool = syncThreadPool;
+        this.tokenService = tokenService;
     }
 
     @Override
@@ -331,13 +335,8 @@ public class UserBackendServiceImpl implements UserBackendService {
     }
 
     @Override
-    public UserRecord resetErrorCount(Long userUU) {
-        UserRecord userRecord = userRecordDao.findOne(userUU);
-        if (userRecord == null) {
-            userRecord = new UserRecord(userUU);
-        }
-        userRecord.setPwdErrorCount(0);
-        return userRecordDao.save(userRecord);
+    public void resetErrorCount(Long userUU) {
+        tokenService.delete("login_count_" + userUU);
     }
 
     private void emailHasRegistered(String mobile) {

+ 3 - 0
sso-manage-console/src/main/resources/config/application-dev.properties

@@ -18,6 +18,9 @@ app.datasource.maxPoolPreparedStatementPerConnectionSize=20
 app.datasource.filters=stat,slf4j
 app.datasource.connectionProperties=druid.stat.mergeSql=false;druid.stat.slowSqlMillis=5000
 
+spring.redis.host=192.168.253.6
+spring.redis.port=6379
+
 spring.jpa.show-sql=false
 spring.jpa.hibernate.ddl-auto=update
 

+ 3 - 0
sso-manage-console/src/main/resources/config/application-prod.properties

@@ -18,6 +18,9 @@ app.datasource.maxPoolPreparedStatementPerConnectionSize=20
 app.datasource.filters=stat,slf4j
 app.datasource.connectionProperties=druid.stat.mergeSql=false;druid.stat.slowSqlMillis=5000
 
+spring.redis.host=10.10.100.200
+spring.redis.port=6379
+
 spring.jpa.show-sql=false
 spring.jpa.hibernate.ddl-auto=update
 

+ 3 - 0
sso-manage-console/src/main/resources/config/application-test.properties

@@ -18,6 +18,9 @@ app.datasource.maxPoolPreparedStatementPerConnectionSize=20
 app.datasource.filters=stat,slf4j
 app.datasource.connectionProperties=druid.stat.mergeSql=false;druid.stat.slowSqlMillis=5000
 
+spring.redis.host=192.168.253.6
+spring.redis.port=6379
+
 spring.jpa.show-sql=false
 spring.jpa.hibernate.ddl-auto=update
 

+ 7 - 5
sso-server/src/main/java/com/uas/sso/controller/LoginController.java

@@ -15,6 +15,7 @@ import com.uas.sso.entity.login.PasswordLogin;
 import com.uas.sso.entity.login.SmsLogin;
 import com.uas.sso.entity.login.TokenLogin;
 import com.uas.sso.entity.Token;
+import com.uas.sso.exception.PasswordErrorException;
 import com.uas.sso.service.AppService;
 import com.uas.sso.service.LoginService;
 import com.uas.sso.service.PersonalAccountService;
@@ -76,7 +77,11 @@ public class LoginController extends BaseController {
     @RequestMapping(method = RequestMethod.POST)
     public ModelMap login(PasswordLogin loginParam) {
         loginParam.setSureCaptcha((String) request.getSession().getAttribute(LOGIN_CAPTCHA));
-        return success(loginService.loginByPassword(loginParam));
+        try {
+            return success(loginService.loginByPassword(loginParam));
+        } catch (PasswordErrorException e) {
+            return error(e.getMessage()).addAttribute("errorCount", e.getCount());
+        }
     }
 
     /**
@@ -220,10 +225,7 @@ public class LoginController extends BaseController {
      */
     @RequestMapping(value = "/getPwdErrorCount", method = RequestMethod.GET)
     public ModelMap getPwdErrorCount(String username) {
-        if (StringUtils.isEmpty(username)) {
-            return error("用户名不能为空");
-        }
-        return success(userService.getPwdErrorCount(username.trim()));
+        return success(loginService.getPwdErrorCount(username));
     }
 
     /**

+ 24 - 0
sso-server/src/main/java/com/uas/sso/exception/PasswordErrorException.java

@@ -0,0 +1,24 @@
+package com.uas.sso.exception;
+
+/**
+ * @author wangmh
+ * @create 2018-08-15 13:46
+ * @desc
+ **/
+public class PasswordErrorException extends Exception {
+    private static final long serialVersionUID = 6091816708317555769L;
+
+    /**
+     * 密码错误次数
+     */
+    private int count;
+
+    public PasswordErrorException(String msg, int errorCount) {
+        super(msg);
+        this.count = errorCount;
+    }
+
+    public int getCount() {
+        return count;
+    }
+}

+ 9 - 1
sso-server/src/main/java/com/uas/sso/service/LoginService.java

@@ -4,6 +4,7 @@ import com.uas.sso.entity.login.ForeignLogin;
 import com.uas.sso.entity.login.PasswordLogin;
 import com.uas.sso.entity.login.SmsLogin;
 import com.uas.sso.entity.login.TokenLogin;
+import com.uas.sso.exception.PasswordErrorException;
 import org.springframework.ui.ModelMap;
 
 /**
@@ -18,7 +19,7 @@ public interface LoginService {
      * @param loginParam
      * @return
      */
-    ModelMap loginByPassword(PasswordLogin loginParam);
+    ModelMap loginByPassword(PasswordLogin loginParam) throws PasswordErrorException;
 
     /**
      * 通过token登录
@@ -40,4 +41,11 @@ public interface LoginService {
      * @return
      */
     ModelMap loginByForeign(ForeignLogin loginParam);
+
+    /**
+     * 获取用户错误次数
+     * @param username 账号
+     * @return
+     */
+    int getPwdErrorCount(String username);
 }

+ 62 - 9
sso-server/src/main/java/com/uas/sso/service/impl/LoginServiceImpl.java

@@ -12,6 +12,7 @@ import com.uas.sso.entity.login.*;
 import com.uas.sso.entity.Token;
 import com.uas.sso.entity.User;
 import com.uas.sso.entity.UserAccount;
+import com.uas.sso.exception.PasswordErrorException;
 import com.uas.sso.exception.VisibleError;
 import com.uas.sso.foreign.entity.ForeignInfo;
 import com.uas.sso.foreign.factory.ForeignFactory;
@@ -32,6 +33,7 @@ import org.springframework.util.StringUtils;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 import java.util.ArrayList;
+import java.util.Calendar;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -76,7 +78,7 @@ public class LoginServiceImpl implements LoginService {
     private static final int PWD_ERROR_THREE_TIME = 3;
 
     @Override
-    public ModelMap loginByPassword(PasswordLogin loginParam) {
+    public ModelMap loginByPassword(PasswordLogin loginParam) throws PasswordErrorException {
         // 校验参数
         if (loginParam == null) {
             throw new VisibleError("参数错误");
@@ -95,7 +97,7 @@ public class LoginServiceImpl implements LoginService {
         }
 
         // 获取密码错误次数
-        Integer pwdErrorCount = getPwdErrorCount(user);
+        Integer pwdErrorCount = getPwdErrorCount(user.getUserUU());
 
         // 校验验证码
         if (pwdErrorCount >= PWD_ERROR_FIVE_TIME) {
@@ -110,7 +112,11 @@ public class LoginServiceImpl implements LoginService {
         }
 
         // 校验密码
-        userService.checkPassword(user.getUserUU(), loginParam.getPassword(), false);
+        String encryPassword = userService.getEncryPassword(Const.ENCRY_FORMAT, loginParam.getPassword(), user.getSalt());
+        if (!encryPassword.equals(user.getPassword())) {
+            int count = addPwdCount(user.getUserUU());
+            throw new PasswordErrorException("您输入的账号或密码有误", count);
+        }
 
         // 校验密码强度,如果和存储的不同,则保存
         int strength = PasswordLevelUtils.checkPasswordLevel(loginParam.getPassword()).getValue();
@@ -206,6 +212,15 @@ public class LoginServiceImpl implements LoginService {
         return login(user.getUserUU(), spaceUU, loginParam).addAttribute("hasRegister", true);
     }
 
+    @Override
+    public int getPwdErrorCount(String username) {
+        User user = userService.findByUsername(username);
+        if (user == null) {
+            throw new VisibleError("用户名不存在");
+        }
+        return getPwdErrorCount(user.getUserUU());
+    }
+
     private ModelMap login(Long userUU, Long spaceUU, BaseLogin loginParam) {
         App app = appService.findOne(loginParam.getAppId());
         if (app == null) {
@@ -286,10 +301,6 @@ public class LoginServiceImpl implements LoginService {
         return data;
     }
 
-    private void resetPwdCount(Long userUU) {
-        tokenService.delete("login_count_" + userUU);
-    }
-
     private ModelMap addOtherAppRequestData(UserAccount userAccount, ModelMap data, BaseLogin loginParam) {
         List<String> loginUrls = appService.findAllLoginUrl();
         boolean loginAll = loginParam.isLoginAll();
@@ -311,8 +322,50 @@ public class LoginServiceImpl implements LoginService {
         return data;
     }
 
-    private Integer getPwdErrorCount(User user) {
-        Token token = tokenService.findOne("login_count_" + user.getUserUU());
+    /**
+     * 获取密码错误次数
+     * @param userUU 用户uu号
+     * @return
+     */
+    private Integer getPwdErrorCount(Long userUU) {
+        Token token = tokenService.findOne("login_count_" + userUU);
         return (Integer) Optional.ofNullable(token).map(Token::getBind).orElse(0);
     }
+
+    /**
+     * 添加密码错误次数
+     * @param userUU 用户uu号
+     * @return
+     */
+    private int addPwdCount(Long userUU) {
+        String tokenId = "login_count_" + userUU;
+        Token token = tokenService.findOne(tokenId);
+        token = token == null ? new Token(0, getSecondsNextEarlyMorning().intValue()) : token;
+        int count = (Integer) Optional.ofNullable(token).map(Token::getBind).orElse(0) + 1;
+        token.setId(tokenId);
+        token.setBind(count);
+        tokenService.save(token);
+        return count;
+    }
+
+    private Long getSecondsNextEarlyMorning() {
+        Calendar cal = Calendar.getInstance();
+        cal.add(Calendar.DAY_OF_YEAR, 1);
+        // 改成这样就好了
+        cal.set(Calendar.HOUR_OF_DAY, 0);
+        cal.set(Calendar.SECOND, 0);
+        cal.set(Calendar.MINUTE, 0);
+        cal.set(Calendar.MILLISECOND, 0);
+        Long seconds = (cal.getTimeInMillis() - System.currentTimeMillis()) / 1000;
+        return seconds.longValue();
+    }
+
+    /**
+     * 重置密码错误次数
+     * @param userUU 用户uu号
+     * @return
+     */
+    private void resetPwdCount(Long userUU) {
+        tokenService.delete("login_count_" + userUU);
+    }
 }

+ 3 - 1
sso-server/src/test/java/com/uas/sso/controller/LoginControllerTest.java

@@ -13,6 +13,7 @@ import org.springframework.ui.ModelMap;
 import org.springframework.util.LinkedMultiValueMap;
 import org.springframework.util.MultiValueMap;
 
+import javax.servlet.http.Cookie;
 import java.io.UnsupportedEncodingException;
 import java.util.List;
 
@@ -60,8 +61,9 @@ public class LoginControllerTest extends BaseControllerTest {
     }
 
     private void checkCookie(MockHttpServletResponse response, String name) {
+        Cookie cookie = response.getCookie("uid");
         String uid = getCookieValue(response, name);
-        Assert.assertNotNull("cookie uid is null", uid);
+        Assert.assertTrue("cookie uid is null", uid != null || cookie != null);
     }
 
     private String getCookieValue(MockHttpServletResponse response, String k) {