Quellcode durchsuchen

fix APP login verification

Alex vor 4 Jahren
Ursprung
Commit
3d1446da2e

+ 1 - 1
ruoyi-app/src/main/java/com/ruoyi/app/controller/TbAppUserController.java → ruoyi-admin/src/main/java/com/ruoyi/web/controller/api/TbAppUserController.java

@@ -1,4 +1,4 @@
-package com.ruoyi.app.controller;
+package com.ruoyi.web.controller.api;
 
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 

+ 1 - 1
ruoyi-app/src/main/java/com/ruoyi/app/annotation/UserLoginToken.java → ruoyi-app/src/main/java/com/ruoyi/app/annotation/AuthToken.java

@@ -10,6 +10,6 @@ import java.lang.annotation.Target;
  */
 @Target({ElementType.METHOD, ElementType.TYPE})
 @Retention(RetentionPolicy.RUNTIME)
-public @interface UserLoginToken {
+public @interface AuthToken {
     boolean required() default true;
 }

+ 7 - 6
ruoyi-app/src/main/java/com/ruoyi/app/base/AppLoginUser.java

@@ -9,9 +9,9 @@ public class AppLoginUser {
     private static final long serialVersionUID = 1L;
 
     /**
-     * 用户唯一标识
+     * 用户标识
      */
-    private String token;
+    private String salt;
 
     /**
      * 登陆时间
@@ -48,11 +48,12 @@ public class AppLoginUser {
      */
     private TbAppUser user;
 
-    public String getToken() {
-        return token;
+    public String getSalt() {
+        return salt;
     }
-    public void setToken(String token) {
-        this.token = token;
+
+    public void setSalt(String salt) {
+        this.salt = salt;
     }
 
     public AppLoginUser() {}

+ 42 - 17
ruoyi-app/src/main/java/com/ruoyi/app/base/AppTokenService.java

@@ -28,7 +28,7 @@ import java.util.concurrent.TimeUnit;
 /**
  * @author Alex
  */
-@Service("TokenService")
+@Service("AppTokenService")
 public class AppTokenService {
 
     /**令牌自定义标识*/
@@ -53,15 +53,39 @@ public class AppTokenService {
      *
      * @return 用户信息
      */
-    public LoginUser getLoginUser(HttpServletRequest request) {
+    public AppLoginUser getLoginUser(HttpServletRequest request) {
         // 获取请求携带的令牌
         String token = getToken(request);
         if (StringUtils.isNotEmpty(token)) {
             Claims claims = parseToken(token);
             // 解析对应的用户信息
-            String uuid = (String) claims.get(Constants.APP_LOGIN_USER_KEY);
-            String userKey = getTokenKey(uuid);
-            LoginUser user = redisCache.getCacheObject(userKey);
+            String mobile = (String) claims.get(Constants.APP_LOGIN_USER_KEY);
+            String salt = (String) claims.get("salt");
+            String userKey = getTokenKey(mobile);
+            AppLoginUser user = redisCache.getCacheObject(userKey);
+            if (!salt.equals(user.getSalt())){
+                return null;
+            }
+            return user;
+        }
+        return null;
+    }
+    /**
+     * 获取用户身份信息
+     *
+     * @return 用户信息
+     */
+    public AppLoginUser getLoginUser(String token) {
+        if (StringUtils.isNotEmpty(token)) {
+            Claims claims = parseToken(token);
+            // 解析对应的用户信息
+            String mobile = (String) claims.get(Constants.APP_LOGIN_USER_KEY);
+            String salt = (String) claims.get("salt");
+            String userKey = getTokenKey(mobile);
+            AppLoginUser user = redisCache.getCacheObject(userKey);
+            if (!salt.equals(user.getSalt())){
+                return null;
+            }
             return user;
         }
         return null;
@@ -70,16 +94,16 @@ public class AppTokenService {
      * 设置用户身份信息
      */
     public void setLoginUser(AppLoginUser loginUser) {
-        if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) {
+        if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getUser().getMobile())) {
             refreshToken(loginUser);
         }
     }
     /**
      * 删除用户身份信息
      */
-    public void delLoginUser(String token) {
-        if (StringUtils.isNotEmpty(token)) {
-            String userKey = getTokenKey(token);
+    public void delLoginUser(String mobile) {
+        if (StringUtils.isNotEmpty(mobile)) {
+            String userKey = getTokenKey(mobile);
             redisCache.deleteObject(userKey);
         }
     }
@@ -90,13 +114,14 @@ public class AppTokenService {
      * @return 令牌
      */
     public String createToken(AppLoginUser loginUser) {
-        String token = IdUtils.fastUUID();
-        loginUser.setToken(token);
+        String salt = IdUtils.fastUUID();
+        loginUser.setSalt(salt);
         setUserAgent(loginUser);
         refreshToken(loginUser);
 
         Map<String, Object> claims = new HashMap<>(1);
-        claims.put(Constants.APP_LOGIN_USER_KEY, token);
+        claims.put(Constants.APP_LOGIN_USER_KEY, loginUser.getUser().getMobile());
+        claims.put("salt", salt);
         return createToken(claims);
     }
     /**
@@ -119,9 +144,9 @@ public class AppTokenService {
      */
     public void refreshToken(AppLoginUser loginUser) {
         loginUser.setLoginTime(System.currentTimeMillis());
-        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
-        // 根据uuid将loginUser缓存
-        String userKey = getTokenKey(loginUser.getToken());
+        loginUser.setExpireTime(loginUser.getLoginTime() + expireTime);
+        // 根据mobile将loginUser缓存
+        String userKey = getTokenKey(loginUser.getUser().getMobile());
         redisCache.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
     }
     /**
@@ -189,7 +214,7 @@ public class AppTokenService {
         return token;
     }
 
-    private String getTokenKey(String uuid) {
-        return Constants.APP_LOGIN_TOKEN_KEY + uuid;
+    private String getTokenKey(String mobile) {
+        return Constants.APP_LOGIN_TOKEN_KEY + mobile;
     }
 }

+ 67 - 31
ruoyi-app/src/main/java/com/ruoyi/app/controller/AppLoginController.java

@@ -1,15 +1,20 @@
 package com.ruoyi.app.controller;
 
 
+import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONObject;
 import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
-import com.ruoyi.app.annotation.UserLoginToken;
+import com.ruoyi.app.annotation.AuthToken;
+import com.ruoyi.app.annotation.PassToken;
 import com.ruoyi.app.base.AppLoginUser;
 import com.ruoyi.app.base.AppTokenService;
 import com.ruoyi.app.domain.TbAppUser;
 import com.ruoyi.app.service.ITbAppUserService;
 import com.ruoyi.app.util.AliSMSUtil;
+import com.ruoyi.common.constant.Constants;
 import com.ruoyi.common.core.domain.AjaxResult;
+import com.ruoyi.common.core.redis.RedisCache;
+import com.ruoyi.common.utils.DateUtils;
 import com.ruoyi.common.utils.StringUtils;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -17,6 +22,8 @@ import lombok.RequiredArgsConstructor;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.web.bind.annotation.*;
 
+import javax.servlet.http.HttpServletRequest;
+import java.util.Date;
 import java.util.Map;
 
 /**
@@ -32,13 +39,16 @@ import java.util.Map;
 public class AppLoginController {
 
     @Autowired
-    AppTokenService tokenService;
+    private RedisCache redisCache;
+    @Autowired
+    AppTokenService appTokenService;
     @Autowired
     private ITbAppUserService userService;
 
     /**
      * 登录
      */
+    @PassToken
     @ApiOperation(value = "APP登录", notes = "APP登录")
     @PostMapping("/login")
     public AjaxResult login(String mobile, String captcha){
@@ -48,24 +58,45 @@ public class AppLoginController {
         if (StringUtils.isBlank(captcha)){
             return AjaxResult.error("验证码不能为空");
         }
-        //手机短信验证
-        boolean ckCaptcha = AliSMSUtil.getInstance().validateSmsCode(mobile, captcha);
-        if (!ckCaptcha) {
-            return AjaxResult.error("验证码错误");
+        TbAppUser appUser = userService.getOne(new QueryWrapper<TbAppUser>()
+                .eq("mobile",mobile)
+        );
+        // 为空则新增
+        if (appUser == null) {
+            appUser = new TbAppUser();
+            Date date = new Date();
+            appUser.setMobile(mobile);
+            appUser.setNickName(mobile);
+            appUser.setRole("USER");
+            appUser.setQrcode(DateUtils.getCurrentTimeRandom());
+            appUser.setCreateTime(date);
+            appUser.setUpdateTime(date);
+            boolean ck = userService.save(appUser);
+            if (!ck){
+                return AjaxResult.error("未知异常,登录失败");
+            }
+            appUser.setCreateBy(appUser.getId());
+            appUser.setUpdateBy(appUser.getId());
+            ck = userService.updateById(appUser);
+            if (!ck){
+                return AjaxResult.error("未知异常,登录失败");
+            }
         }
 
+        //手机短信验证 // TODO 调试通过,以后测试在放开注释
+//        boolean ckCaptcha = AliSMSUtil.getInstance().validateSmsCode(mobile, captcha);
+//        if (!ckCaptcha) {
+//            return AjaxResult.error("验证码错误");
+//        }
+
+        //每次登录前,先删除缓存,保证登录唯一性
+        appTokenService.delLoginUser(mobile);
         JSONObject jsonObject = new JSONObject();
-        TbAppUser userForBase = userService.getOne(new QueryWrapper<TbAppUser>()
-            .eq("mobile",mobile)
-        );
-        if(userForBase == null){
-            return AjaxResult.error("用户不存在");
-        }
         AppLoginUser loginUser =  new AppLoginUser();
-        loginUser.setUser(userForBase);
-        String token = tokenService.createToken(loginUser);
+        loginUser.setUser(appUser);
+        String token = appTokenService.createToken(loginUser);
         jsonObject.put("token", token);
-        jsonObject.put("user", userForBase);
+        jsonObject.put("user", appUser);
         return AjaxResult.success(jsonObject);
     }
 
@@ -76,21 +107,12 @@ public class AppLoginController {
      * @param mobile 手机号码
      * @return
      */
+    @PassToken
     @ApiOperation(value = "发送短信验证码", notes = "发送短信验证码")
     @GetMapping("/captchaSend")
     public AjaxResult sendCaptcha(Integer type, String mobile){
-        TbAppUser user = userService.getOne(new QueryWrapper<TbAppUser>()
-                .eq("mobile",mobile)
-        );
-
-        //注册
-        if (type == 1){
-
-        }
-
-        if(user == null || user.getId() == null){
-
-            return AjaxResult.error("用户不存在");
+        if(StringUtils.isBlank(mobile)){
+            return AjaxResult.error("请输入手机号");
         }
         Map<String,String> map = AliSMSUtil.getInstance().sendSmsCode(type, mobile);
         if(map.get("code").equals("200")) {
@@ -105,6 +127,7 @@ public class AppLoginController {
      * @param captcha
      * @return
      */
+    @PassToken
     @ApiOperation(value = "校验短信验证码", notes = "校验短信验证码")
     @GetMapping("/captchaValidate")
     public AjaxResult validateCaptcha(String mobile, String captcha){
@@ -123,10 +146,23 @@ public class AppLoginController {
     }
 
 
+    @ApiOperation(value = "getUser", notes = "getUser")
+//    @AuthToken
+    @GetMapping("/getLoginUser")
+    public AjaxResult getLoginUser(HttpServletRequest request){
+        AppLoginUser user = appTokenService.getLoginUser(request);
+        return AjaxResult.success(user);
+    }
+
+    public static void main(String[] args) {
+//        System.out.println(DateUtils.getCurrentTimeRandom());
 
-    @UserLoginToken
-    @GetMapping("/getMessage")
-    public String getMessage(){
-        return "你已通过验证";
+        String code = "1111111";
+        String params = "{\"code1\":\""+code+"\"}";
+        JSONObject jsonObject = JSON.parseObject(params);
+        jsonObject.getString("code");
+        System.out.println(jsonObject.getString("code"));
     }
+
+
 }

+ 16 - 25
ruoyi-app/src/main/java/com/ruoyi/app/interceptor/AuthenticationInterceptor.java

@@ -1,12 +1,8 @@
 package com.ruoyi.app.interceptor;
 
-import com.auth0.jwt.JWT;
-import com.auth0.jwt.JWTVerifier;
-import com.auth0.jwt.algorithms.Algorithm;
-import com.auth0.jwt.exceptions.JWTDecodeException;
-import com.auth0.jwt.exceptions.JWTVerificationException;
 import com.ruoyi.app.annotation.PassToken;
-import com.ruoyi.app.annotation.UserLoginToken;
+import com.ruoyi.app.base.AppLoginUser;
+import com.ruoyi.app.base.AppTokenService;
 import com.ruoyi.app.domain.TbAppUser;
 import com.ruoyi.app.service.ITbAppUserService;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -26,6 +22,8 @@ import java.lang.reflect.Method;
 public class AuthenticationInterceptor implements HandlerInterceptor {
     @Autowired
     ITbAppUserService userService;
+    @Autowired
+    AppTokenService appTokenService;
     @Override
     public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object object) throws Exception {
         String token = httpServletRequest.getHeader("token");// 从 http 请求头中取出 token
@@ -43,35 +41,28 @@ public class AuthenticationInterceptor implements HandlerInterceptor {
             }
         }
         //检查有没有需要用户权限的注解
-        if (method.isAnnotationPresent(UserLoginToken.class)) {
-            UserLoginToken userLoginToken = method.getAnnotation(UserLoginToken.class);
-            if (userLoginToken.required()) {
+//        if (method.isAnnotationPresent(AuthToken.class)) {
+//            AuthToken authToken = method.getAnnotation(AuthToken.class);
+//            if (authToken.required()) {
                 // 执行认证
                 if (token == null) {
                     throw new RuntimeException("无token,请重新登录");
                 }
-                // 获取 token 中的 user id
-                String userId;
-                try {
-                    userId = JWT.decode(token).getAudience().get(0);
-                } catch (JWTDecodeException j) {
-                    throw new RuntimeException("401");
+                // 获取 token 中的 loginUser
+                AppLoginUser loginUser = appTokenService.getLoginUser(token);
+                if (loginUser == null) {
+                    throw new RuntimeException("用户不存在,请重新登录");
                 }
-                TbAppUser user = userService.getById(userId);
+                TbAppUser user = loginUser.getUser();
                 if (user == null) {
                     throw new RuntimeException("用户不存在,请重新登录");
                 }
                 // 验证 token
-                JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(user.getMobile())).build();
-                try {
-                    jwtVerifier.verify(token);
-                } catch (JWTVerificationException e) {
-                    throw new RuntimeException("401");
-                }
+                appTokenService.verifyToken(loginUser);
                 return true;
-            }
-        }
-        return true;
+//            }
+//        }
+//        return true;
     }
 
     @Override

+ 1 - 1
ruoyi-app/src/main/java/com/ruoyi/app/interceptor/GloablExceptionHandler.java

@@ -19,6 +19,6 @@ public class GloablExceptionHandler {
             msg = "服务器出错";
             return AjaxResult.error(msg);
         }
-        return AjaxResult.success(msg);
+        return AjaxResult.error(msg);
     }
 }

+ 0 - 19
ruoyi-app/src/main/java/com/ruoyi/app/util/AliSMSUtil.java

@@ -106,7 +106,6 @@ public class AliSMSUtil {
      * @return 成功返回true,
      */
     public Boolean validateSmsCode(String phone,String code){
-        boolean istrue=false;
         //没有记录
         if (CodeMap.size()<=0){
             return false;
@@ -130,24 +129,6 @@ public class AliSMSUtil {
         return false;
     }
 
-    /**
-     * 会员充值
-     * @param phone 电话号码
-     * @param store 商家名称
-     * @param money 充值金额
-     * @param newMoney 充值后会员余额
-     * @return
-     */
-    public Map<String,String> sendSmsHycz(String phone,String store,String money,String newMoney){
-        Map<String,String> map = new HashMap<>();
-        String templateCode = "SMS_143706044";
-        String params = "{\"store\":\""+store+"\",\"money\":\""+money+"\",\"newMoney\":\""+newMoney+"\"}";
-        map = sendSms(phone,params,SIGN_NAME,templateCode);
-        return map;
-    }
-
-
-
     private Map<String,String> sendSms(String phone,String params,String signName,String templateCode){
         Map<String,String> map = new HashMap<>();
         //可自助调整超时时间

+ 1 - 1
ruoyi-app/src/main/resources/application.yml

@@ -115,7 +115,7 @@ swagger:
   # 是否开启swagger
   enabled: true
   # 请求前缀
-  pathMapping: /api
+  pathMapping: /
 
 # 防止XSS攻击
 xss: 

+ 8 - 0
ruoyi-common/src/main/java/com/ruoyi/common/utils/DateUtils.java

@@ -4,6 +4,8 @@ import java.lang.management.ManagementFactory;
 import java.text.ParseException;
 import java.text.SimpleDateFormat;
 import java.util.Date;
+
+import cn.hutool.core.util.RandomUtil;
 import org.apache.commons.lang3.time.DateFormatUtils;
 
 /**
@@ -152,4 +154,10 @@ public class DateUtils extends org.apache.commons.lang3.time.DateUtils
         // long sec = diff % nd % nh % nm / ns;
         return day + "天" + hour + "小时" + min + "分钟";
     }
+
+    public static String getCurrentTimeRandom(){
+//        SimpleDateFormat dateformat = new SimpleDateFormat("yy.MM.dd.HH.mm.ss.SSSS.");
+//        String dateStr = dateformat.format(System.currentTimeMillis());
+        return String.valueOf(System.currentTimeMillis())+ RandomUtil.randomInt(1,99);
+    }
 }

+ 1 - 4
ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java

@@ -97,7 +97,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                 // 过滤请求
                 .authorizeRequests()
                 // 对于登录login 验证码captchaImage 允许匿名访问
-                .antMatchers("/login", "/captchaImage").anonymous()
+                .antMatchers("/login", "/captchaImage", "/app/**").anonymous()
                 .antMatchers(
                         HttpMethod.GET,
                         "/*.html",
@@ -114,9 +114,6 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter
                 .antMatchers("/*/api-docs").anonymous()
                 .antMatchers("/druid/**").anonymous()
                 .antMatchers("/template/**").anonymous()
-                .antMatchers("/app/login").anonymous()
-                .antMatchers("/app/captchaSend").anonymous()
-                .antMatchers("/app/captchaValidate").anonymous()
                 // 除上面外的所有请求全部需要鉴权认证
                 .anyRequest().authenticated()
                 .and()

+ 2 - 2
ruoyi-system/src/main/java/com/ruoyi/app/domain/TbAppUser.java

@@ -70,13 +70,13 @@ public class TbAppUser implements Serializable {
     private String verCode;
 
     /** 创建者 */
-    private String createBy;
+    private Long createBy;
 
     /** 创建时间 */
     private Date createTime;
 
     /** 更新者 */
-    private String updateBy;
+    private Long updateBy;
 
     /** 更新时间 */
     private Date updateTime;