瀏覽代碼

1.对接Taku 广告源管理
2.安卓应用微信登录
3.app集成shiro认证
4.答题app字段补充
5.广告API远程调用,agent新增广告应用

marxjaw 5 月之前
父節點
當前提交
aeb7820910
共有 59 個文件被更改,包括 1806 次插入104 次删除
  1. 23 0
      yt-advertise/advertise-feign/pom.xml
  2. 13 0
      yt-advertise/advertise-feign/src/main/java/com/ytpm/feign/AdvertiseFeign.java
  3. 11 0
      yt-advertise/advertise-service/src/main/java/com/ytpm/controller/AdvertiseController.java
  4. 31 2
      yt-advertise/advertise-service/src/main/java/com/ytpm/service/TakuApiService.java
  5. 64 2
      yt-advertise/advertise-service/src/main/java/com/ytpm/service/impl/TakuApiServiceImpl.java
  6. 2 0
      yt-advertise/advertise-service/src/main/java/com/ytpm/util/TakuRequestUtil.java
  7. 5 0
      yt-advertise/pom.xml
  8. 10 0
      yt-agent/agent-service/pom.xml
  9. 13 0
      yt-agent/agent-service/src/main/java/com/ytpm/controller/AppController.java
  10. 6 0
      yt-agent/agent-service/src/main/java/com/ytpm/dao/AgentAppMapper.java
  11. 13 0
      yt-agent/agent-service/src/main/java/com/ytpm/service/AgentAppService.java
  12. 28 0
      yt-agent/agent-service/src/main/java/com/ytpm/service/impl/AgentAppServiceImpl.java
  13. 1 1
      yt-agent/agent-service/src/main/resources/bootstrap.yml
  14. 3 0
      yt-agent/agent-service/src/main/resources/mapper/AgentAppMapper.xml
  15. 37 0
      yt-app/app-feign/pom.xml
  16. 7 0
      yt-app/app-feign/src/main/java/com/ytpm/feign/AppFeign.java
  17. 12 4
      yt-app/app-service/pom.xml
  18. 31 0
      yt-app/app-service/src/main/java/com/ytpm/config/YtWebMvcConfigurerAdapter.java
  19. 36 0
      yt-app/app-service/src/main/java/com/ytpm/config/interceptor/HttpInterceptor.java
  20. 64 0
      yt-app/app-service/src/main/java/com/ytpm/config/interceptor/PostHttpRequestInterceptor.java
  21. 88 0
      yt-app/app-service/src/main/java/com/ytpm/config/interceptor/UserActionInterceptor.java
  22. 300 0
      yt-app/app-service/src/main/java/com/ytpm/config/shiro/ShiroAutoConfiguration.java
  23. 18 0
      yt-app/app-service/src/main/java/com/ytpm/config/shiro/ShiroLifecycleBeanPostProcessorConfig.java
  24. 59 0
      yt-app/app-service/src/main/java/com/ytpm/config/shiro/UserRealm.java
  25. 116 13
      yt-app/app-service/src/main/java/com/ytpm/controller/WxController.java
  26. 0 14
      yt-app/app-service/src/main/java/com/ytpm/dao/AgentUserMapper.java
  27. 39 0
      yt-app/app-service/src/main/java/com/ytpm/dao/AppUserMapper.java
  28. 2 2
      yt-app/app-service/src/main/java/com/ytpm/dao/LoginRecordMapper.java
  29. 16 0
      yt-app/app-service/src/main/java/com/ytpm/dao/QuestionMapper.java
  30. 28 0
      yt-app/app-service/src/main/java/com/ytpm/model/ActiveUser.java
  31. 30 0
      yt-app/app-service/src/main/java/com/ytpm/model/YtDyzLoginRecord.java
  32. 15 0
      yt-app/app-service/src/main/java/com/ytpm/model/YtDyzPowerRecord.java
  33. 96 0
      yt-app/app-service/src/main/java/com/ytpm/model/YtDyzUser.java
  34. 10 0
      yt-app/app-service/src/main/java/com/ytpm/service/AppUserService.java
  35. 22 0
      yt-app/app-service/src/main/java/com/ytpm/service/impl/AppUserServiceImpl.java
  36. 14 0
      yt-app/app-service/src/main/java/com/ytpm/service/impl/QuestionServiceImpl.java
  37. 41 0
      yt-app/app-service/src/main/java/com/ytpm/util/MyRedisManager.java
  38. 71 0
      yt-app/app-service/src/main/java/com/ytpm/util/ShiroFilterUtils.java
  39. 58 0
      yt-app/app-service/src/main/java/com/ytpm/util/ShiroSubjectUtil.java
  40. 29 0
      yt-app/app-service/src/main/java/com/ytpm/util/WebUtils.java
  41. 0 12
      yt-app/app-service/src/main/resources/mapper/AgentUserMapper.xml
  42. 86 0
      yt-app/app-service/src/main/resources/mapper/AppUserMapper.xml
  43. 8 10
      yt-app/app-service/src/main/resources/mapper/LoginRecordMapper.xml
  44. 23 0
      yt-app/app-service/src/main/resources/mapper/QuestionMapper.xml
  45. 1 0
      yt-app/pom.xml
  46. 31 0
      yt-common/src/main/java/com/ytpm/advertise/param/UnitsItemParam.java
  47. 26 0
      yt-common/src/main/java/com/ytpm/advertise/param/UnitsListParam.java
  48. 15 0
      yt-common/src/main/java/com/ytpm/advertise/param/UnitsParam.java
  49. 14 0
      yt-common/src/main/java/com/ytpm/advertise/view/SaveItemsView.java
  50. 17 0
      yt-common/src/main/java/com/ytpm/advertise/view/UnitsAdSourceView.java
  51. 15 0
      yt-common/src/main/java/com/ytpm/advertise/view/UnitsAddResponse.java
  52. 22 0
      yt-common/src/main/java/com/ytpm/advertise/view/UnitsItemsView.java
  53. 16 0
      yt-common/src/main/java/com/ytpm/advertise/view/UnitsListView.java
  54. 13 0
      yt-common/src/main/java/com/ytpm/advertise/view/UnitsUpdateResponse.java
  55. 18 0
      yt-common/src/main/java/com/ytpm/advertise/view/UnitsView.java
  56. 30 0
      yt-common/src/main/java/com/ytpm/app/view/YtAppListView.java
  57. 7 43
      yt-common/src/main/java/com/ytpm/constant/StrConstant.java
  58. 1 0
      yt-common/src/main/java/com/ytpm/general/RepMessage.java
  59. 1 1
      yt-common/src/main/java/com/ytpm/util/IDUtil.java

+ 23 - 0
yt-advertise/advertise-feign/pom.xml

@@ -0,0 +1,23 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.ytpm</groupId>
+        <artifactId>yt-advertise</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>advertise-feign</artifactId>
+    <packaging>jar</packaging>
+
+    <name>advertise-feign</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+
+    </dependencies>
+</project>

+ 13 - 0
yt-advertise/advertise-feign/src/main/java/com/ytpm/feign/AdvertiseFeign.java

@@ -0,0 +1,13 @@
+package com.ytpm.feign;
+
+import com.ytpm.advertise.param.AddAppParam;
+import com.ytpm.advertise.view.AddAppResponse;
+import com.ytpm.general.Result;
+import org.springframework.cloud.openfeign.FeignClient;
+import org.springframework.web.bind.annotation.PostMapping;
+
+@FeignClient(name = "advertise-service")
+public interface AdvertiseFeign {
+    @PostMapping("/advertise/addApp")
+    Result<AddAppResponse> addApp(AddAppParam param);
+}

+ 11 - 0
yt-advertise/advertise-service/src/main/java/com/ytpm/controller/AdvertiseController.java

@@ -1,5 +1,7 @@
 package com.ytpm.controller;
 
+import com.ytpm.advertise.param.AddAppParam;
+import com.ytpm.advertise.view.AddAppResponse;
 import com.ytpm.advertise.view.AppV1View;
 import com.ytpm.agent.param.ChannelParam;
 import com.ytpm.general.Result;
@@ -38,4 +40,13 @@ public class AdvertiseController {
     public ResultTable<AppV1View> getAppList() {
         return takuApiService.getAppList();
     }
+
+    /**
+     * 新增应用
+     */
+    @ApiOperation("新增应用")
+    @PostMapping("/addApp")
+    public Result<AddAppResponse> addApp(AddAppParam param) {
+        return takuApiService.addApps(param);
+    }
 }

+ 31 - 2
yt-advertise/advertise-service/src/main/java/com/ytpm/service/TakuApiService.java

@@ -2,8 +2,13 @@ package com.ytpm.service;
 
 import com.ytpm.advertise.param.AddPlacementParam;
 import com.ytpm.advertise.param.Network;
+import com.ytpm.advertise.param.UnitsListParam;
+import com.ytpm.advertise.param.UnitsParam;
+import com.ytpm.advertise.view.AddAppResponse;
 import com.ytpm.advertise.view.AddPlacementResponse;
 import com.ytpm.advertise.view.AppV1View;
+import com.ytpm.advertise.view.UnitsListView;
+import com.ytpm.advertise.view.UnitsView;
 import com.ytpm.agent.param.ChannelParam;
 import com.ytpm.general.Result;
 import com.ytpm.general.ResultTable;
@@ -14,9 +19,8 @@ import java.util.List;
 public interface TakuApiService {
     /**
      * 新增应用
-     * @return
      */
-   Result<?> addApps(AddAppParam param);
+    Result<AddAppResponse> addApps(AddAppParam param);
     /**
      * Taku应用关联广告平台
      */
@@ -44,4 +48,29 @@ public interface TakuApiService {
      * 删除广告位
      */
     Result<?> delPlacement(List<String> placementIds);
+
+    /**
+     * 获取广告源列表
+     */
+    ResultTable<UnitsListView> getUnitsList(UnitsListParam unitsListParam);
+
+    /**
+     * 获取广告源详情
+     */
+    ResultTable<UnitsView> getUnitsView(List<Integer> ids);
+
+    /**
+     * 保存广告源信息
+     */
+    Result<?> saveUnits(UnitsParam param);
+
+    /**
+     * 修改广告源信息
+     */
+    Result<?> updateUnits(UnitsParam param);
+
+    /**
+     * 删除广告源
+     */
+    Result<?> delUnits(List<Integer> adsource_ids);
 }

+ 64 - 2
yt-advertise/advertise-service/src/main/java/com/ytpm/service/impl/TakuApiServiceImpl.java

@@ -1,5 +1,6 @@
 package com.ytpm.service.impl;
 
+import cn.hutool.core.collection.CollUtil;
 import com.alibaba.fastjson.JSON;
 import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
@@ -9,8 +10,15 @@ import com.ytpm.advertise.param.AppAuthContent;
 import com.ytpm.advertise.param.AuthContent;
 import com.ytpm.advertise.param.Network;
 import com.ytpm.advertise.param.NetworkAppInfo;
+import com.ytpm.advertise.param.UnitsListParam;
+import com.ytpm.advertise.param.UnitsParam;
+import com.ytpm.advertise.view.AddAppResponse;
 import com.ytpm.advertise.view.AddPlacementResponse;
 import com.ytpm.advertise.view.AppV1View;
+import com.ytpm.advertise.view.UnitsAddResponse;
+import com.ytpm.advertise.view.UnitsListView;
+import com.ytpm.advertise.view.UnitsUpdateResponse;
+import com.ytpm.advertise.view.UnitsView;
 import com.ytpm.agent.param.ChannelParam;
 import com.ytpm.enums.OpenReportEnum;
 import com.ytpm.general.RepMessage;
@@ -37,11 +45,14 @@ public class TakuApiServiceImpl implements TakuApiService {
      * 新增或修改应用
      */
     @Override
-    public Result<?> addApps(AddAppParam param) {
+    public Result<AddAppResponse> addApps(AddAppParam param) {
+        //API支持多个添加,我们这里只添加一个
         JSONObject object = new JSONObject();
         object.put("items",Collections.singletonList(param));
+        //若添加成功,API返回应用uuid和 app_key
         String res = TakuRequestUtil.doRequest(HttpGet.METHOD_NAME, API_VERSION_V3+"/apps", object.toJSONString());
-        return Result.resultOk(RepMessage.SAVE_SUCCESS,res);
+        AddAppResponse response = JSON.parseObject(res, AddAppResponse.class);
+        return Result.resultOk(RepMessage.SAVE_SUCCESS,response);
     }
 
     /**
@@ -120,4 +131,55 @@ public class TakuApiServiceImpl implements TakuApiService {
         TakuRequestUtil.doRequest(HttpGet.METHOD_NAME, API_VERSION_V1+"/del_placements", object.toJSONString());
         return Result.resultOk(RepMessage.DELETE_SUCCESS);
     }
+
+    /**
+     * 获取广告源列表
+     */
+    @Override
+    public ResultTable<UnitsListView> getUnitsList(UnitsListParam unitsListParam) {
+        String result = TakuRequestUtil.doRequest(HttpGet.METHOD_NAME, API_VERSION_V3+"/units/list", JSON.toJSONString(unitsListParam));
+        return ResultTable.resultTableOk(new PageInfo<>(JSON.parseArray(result, UnitsListView.class)));
+    }
+
+    /**
+     * 查询广告源详情
+     */
+    @Override
+    public ResultTable<UnitsView> getUnitsView(List<Integer> ids) {
+        JSONObject object = new JSONObject();
+        object.put("ids",ids);
+        String result = TakuRequestUtil.doRequest(HttpGet.METHOD_NAME, API_VERSION_V3+"/units", JSON.toJSONString(object));
+        return ResultTable.resultTableOk(new PageInfo<>(JSON.parseArray(result, UnitsView.class)));
+    }
+
+    /**
+     * 保存广告源信息
+     */
+    @Override
+    public Result<?> saveUnits(UnitsParam param) {
+        String result = TakuRequestUtil.doRequest(HttpPost.METHOD_NAME, API_VERSION_V3+"/units", JSON.toJSONString(param));
+        return Result.resultObjOk(JSONObject.parseObject(result, UnitsAddResponse.class));
+    }
+
+    /**
+     * 修改广告源信息
+     */
+    @Override
+    public Result<?> updateUnits(UnitsParam param) {
+        String result = TakuRequestUtil.doRequest(HttpPost.METHOD_NAME, API_VERSION_V3+"/units", JSON.toJSONString(param));
+        return Result.resultObjOk(JSONObject.parseObject(result, UnitsUpdateResponse.class));
+    }
+
+    /**
+     * 删除广告源
+     */
+    @Override
+    public Result<?> delUnits(List<Integer> adsource_ids) {
+        JSONObject object = new JSONObject();
+        object.put("adsource_ids",adsource_ids);
+        TakuRequestUtil.doRequest(HttpPost.METHOD_NAME, API_VERSION_V1+"/del_units", JSON.toJSONString(object));
+        return Result.resultOk(RepMessage.DELETE_SUCCESS);
+    }
+
+
 }

+ 2 - 0
yt-advertise/advertise-service/src/main/java/com/ytpm/util/TakuRequestUtil.java

@@ -14,6 +14,7 @@ import com.ytpm.enums.AndroidFirstCategoryEnum;
 import com.ytpm.enums.AndroidSecondCategoryEnum;
 import com.ytpm.advertise.param.AddAppParam;
 import com.ytpm.enums.OpenReportEnum;
+import com.ytpm.handle.CustomerException;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.codec.digest.DigestUtils;
 import org.apache.http.HttpEntity;
@@ -79,6 +80,7 @@ public class TakuRequestUtil {
         } catch (Exception e) {
             e.printStackTrace();
             log.error(e.getMessage());
+            throw new CustomerException(e.getMessage());
         }
         return result;
     }

+ 5 - 0
yt-advertise/pom.xml

@@ -12,6 +12,7 @@
     <description>广告API</description>
     <modules>
         <module>advertise-service</module>
+        <module>advertise-feign</module>
     </modules>
 
     <properties>
@@ -98,6 +99,10 @@
                     <artifactId>jsr305</artifactId>
                     <groupId>com.google.code.findbugs</groupId>
                 </exclusion>
+                <exclusion>
+                    <groupId>org.springframework.cloud</groupId>
+                    <artifactId>spring-cloud-starter-oauth2</artifactId>
+                </exclusion>
             </exclusions>
         </dependency>
         <dependency>

+ 10 - 0
yt-agent/agent-service/pom.xml

@@ -42,6 +42,16 @@
             <artifactId>risk-feign</artifactId>
             <version>1.0-SNAPSHOT</version>
         </dependency>
+        <dependency>
+            <groupId>com.ytpm</groupId>
+            <artifactId>app-feign</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
+        <dependency>
+            <groupId>com.ytpm</groupId>
+            <artifactId>advertise-feign</artifactId>
+            <version>1.0-SNAPSHOT</version>
+        </dependency>
     </dependencies>
     <build>
         <finalName>agent-service</finalName>

+ 13 - 0
yt-agent/agent-service/src/main/java/com/ytpm/controller/AppController.java

@@ -1,13 +1,18 @@
 package com.ytpm.controller;
 
+import com.ytpm.advertise.param.AddAppParam;
 import com.ytpm.agent.view.AgentEnableAppView;
 import com.ytpm.agent.view.AgentUserInfo;
+import com.ytpm.app.view.YtAppListView;
+import com.ytpm.general.Result;
 import com.ytpm.general.ResultTable;
 import com.ytpm.service.AgentAppService;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import org.springframework.security.core.annotation.AuthenticationPrincipal;
 import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
 import org.springframework.web.bind.annotation.RestController;
 import springfox.documentation.annotations.ApiIgnore;
@@ -31,4 +36,12 @@ public class AppController {
         return agentAppService.getEnabledList(userInfo.getUserId());
     }
 
+    /**
+     * 新增应用
+     */
+    @ApiOperation("新增应用")
+    @PostMapping("/addApp")
+    public Result<?> addApp(@RequestBody AddAppParam param){
+        return agentAppService.addApp(param);
+    }
 }

+ 6 - 0
yt-agent/agent-service/src/main/java/com/ytpm/dao/AgentAppMapper.java

@@ -1,6 +1,7 @@
 package com.ytpm.dao;
 
 import com.ytpm.agent.view.AgentEnableAppView;
+import com.ytpm.app.view.YtAppListView;
 import org.apache.ibatis.annotations.Param;
 import org.mapstruct.Mapper;
 
@@ -12,4 +13,9 @@ public interface AgentAppMapper {
      * 查询渠道启用的应用列表
      */
     List<AgentEnableAppView> getEnabledList(@Param("userId") String userId);
+
+    /**
+     *
+     */
+    List<YtAppListView> searchAppList();
 }

+ 13 - 0
yt-agent/agent-service/src/main/java/com/ytpm/service/AgentAppService.java

@@ -1,6 +1,9 @@
 package com.ytpm.service;
 
+import com.ytpm.advertise.param.AddAppParam;
 import com.ytpm.agent.view.AgentEnableAppView;
+import com.ytpm.app.view.YtAppListView;
+import com.ytpm.general.Result;
 import com.ytpm.general.ResultTable;
 
 public interface AgentAppService {
@@ -8,4 +11,14 @@ public interface AgentAppService {
      * 查询渠道启用的应用列表
      */
     ResultTable<AgentEnableAppView> getEnabledList(String userId);
+
+    /**
+     * 查询应用列表
+     */
+    ResultTable<YtAppListView> searchAppList();
+
+    /**
+     * 新增应用
+     */
+    Result<?> addApp(AddAppParam param);
 }

+ 28 - 0
yt-agent/agent-service/src/main/java/com/ytpm/service/impl/AgentAppServiceImpl.java

@@ -1,8 +1,13 @@
 package com.ytpm.service.impl;
 
 import com.github.pagehelper.PageInfo;
+import com.ytpm.advertise.param.AddAppParam;
+import com.ytpm.advertise.view.AddAppResponse;
 import com.ytpm.agent.view.AgentEnableAppView;
+import com.ytpm.app.view.YtAppListView;
 import com.ytpm.dao.AgentAppMapper;
+import com.ytpm.feign.AdvertiseFeign;
+import com.ytpm.general.Result;
 import com.ytpm.general.ResultTable;
 import com.ytpm.service.AgentAppService;
 import org.springframework.stereotype.Service;
@@ -14,6 +19,8 @@ public class AgentAppServiceImpl implements AgentAppService {
 
     @Resource
     private AgentAppMapper agentAppMapper;
+    @Resource
+    private AdvertiseFeign advertiseFeign;
 
     /**
      * 查询渠道启用的应用列表
@@ -22,4 +29,25 @@ public class AgentAppServiceImpl implements AgentAppService {
     public ResultTable<AgentEnableAppView> getEnabledList(String userId) {
         return ResultTable.resultTableOk(new PageInfo<>(agentAppMapper.getEnabledList(userId)));
     }
+
+
+    /**
+     * 查询应用列表
+     */
+    @Override
+    public ResultTable<YtAppListView> searchAppList() {
+        return ResultTable.resultTableOk(new PageInfo<>(agentAppMapper.searchAppList()));
+    }
+
+    /**
+     * 新增应用
+     */
+    @Override
+    public Result<?> addApp(AddAppParam param) {
+        //调用广告平台API 增加应用
+        Result<AddAppResponse> result = advertiseFeign.addApp(param);
+        //TODO 数据库存储应用信息
+
+        return null;
+    }
 }

+ 1 - 1
yt-agent/agent-service/src/main/resources/bootstrap.yml

@@ -1,6 +1,6 @@
 spring:
   profiles:
-    active: dev
+    active: local
 ---
 spring:
   profiles: local

+ 3 - 0
yt-agent/agent-service/src/main/resources/mapper/AgentAppMapper.xml

@@ -24,4 +24,7 @@
             ya.enabled = 1
           AND ya.user_id = #{userId}
     </select>
+    <select id="searchAppList" resultType="com.ytpm.app.view.YtAppListView">
+
+    </select>
 </mapper>

+ 37 - 0
yt-app/app-feign/pom.xml

@@ -0,0 +1,37 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>com.ytpm</groupId>
+        <artifactId>yt-app</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+
+    <artifactId>app-feign</artifactId>
+    <packaging>jar</packaging>
+
+    <name>app-feign</name>
+    <url>http://maven.apache.org</url>
+
+    <properties>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    </properties>
+
+    <dependencies>
+
+    </dependencies>
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.springframework.boot</groupId>
+                <artifactId>spring-boot-maven-plugin</artifactId>
+                <version>${spring-boot.version}</version>
+                <configuration>
+                    <skip>
+                        true
+                    </skip>
+                </configuration>
+            </plugin>
+        </plugins>
+    </build>
+</project>

+ 7 - 0
yt-app/app-feign/src/main/java/com/ytpm/feign/AppFeign.java

@@ -0,0 +1,7 @@
+package com.ytpm.feign;
+
+import org.springframework.cloud.openfeign.FeignClient;
+
+@FeignClient(name = "app-service")
+public interface AppFeign {
+}

+ 12 - 4
yt-app/app-service/pom.xml

@@ -11,13 +11,25 @@
     <packaging>jar</packaging>
 
     <name>app-service</name>
+    <description>答题APP</description>
     <url>http://maven.apache.org</url>
 
     <properties>
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <shiro.version>1.4.1</shiro.version>
     </properties>
 
     <dependencies>
+        <dependency>
+            <groupId>org.apache.shiro</groupId>
+            <artifactId>shiro-spring</artifactId>
+            <version>${shiro.version}</version>
+        </dependency>
+        <dependency>
+            <groupId>org.crazycake</groupId>
+            <artifactId>shiro-redis</artifactId>
+            <version>3.2.3</version>
+        </dependency>
         <dependency>
             <groupId>mysql</groupId>
             <artifactId>mysql-connector-java</artifactId>
@@ -32,10 +44,6 @@
             <artifactId>risk-feign</artifactId>
             <version>1.0-SNAPSHOT</version>
         </dependency>
-        <dependency>
-            <groupId>org.springframework.boot</groupId>
-            <artifactId>spring-boot-starter-security</artifactId>
-        </dependency>
     </dependencies>
     <build>
         <finalName>app-service</finalName>

+ 31 - 0
yt-app/app-service/src/main/java/com/ytpm/config/YtWebMvcConfigurerAdapter.java

@@ -0,0 +1,31 @@
+package com.ytpm.config;
+
+import com.ytpm.config.interceptor.HttpInterceptor;
+import com.ytpm.config.interceptor.PostHttpRequestInterceptor;
+import com.ytpm.config.interceptor.UserActionInterceptor;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
+import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
+
+/**
+ * 自定义拦截器
+ */
+@Configuration
+public class YtWebMvcConfigurerAdapter implements WebMvcConfigurer {
+
+    @Autowired
+    private UserActionInterceptor userActionInterceptor;
+    @Autowired
+    private PostHttpRequestInterceptor postHttpRequestInterceptor;
+
+    @Override
+    public void addInterceptors(InterceptorRegistry registry) {
+        registry.addInterceptor(new HttpInterceptor()).addPathPatterns("/**").excludePathPatterns("/resources/**");
+        registry.addInterceptor(userActionInterceptor).addPathPatterns("/**").excludePathPatterns("/wx/**","/question/**","/sys/toLogin*","/login/**","/resources/**","/fastDFS/**","/error",
+                "/doc.html","/api/v2/**","/v2/api-docs", "/configuration/ui", "/swagger-resources", "/configuration/security",
+                "/swagger-ui.html", "/webjars/**","/swagger-resources/configuration/ui","/swagger-ui.html");
+        registry.addInterceptor(postHttpRequestInterceptor).addPathPatterns("/**").excludePathPatterns("/sys/toLogin*","/resources/**"
+                ,"/login/**","/fastDFS/**","/error","/file/**","/customer/saveImageByOne");
+    }
+}

+ 36 - 0
yt-app/app-service/src/main/java/com/ytpm/config/interceptor/HttpInterceptor.java

@@ -0,0 +1,36 @@
+package com.ytpm.config.interceptor;
+
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.util.Date;
+
+public class HttpInterceptor implements HandlerInterceptor {
+
+    @Override
+    public boolean preHandle(HttpServletRequest request,
+                             HttpServletResponse response, Object obj) throws Exception {
+        return true;
+    }
+
+    /**
+     * 请求处理之后调用;在视图渲染之前,controller处理之后。
+     */
+    @Override
+    public void postHandle(HttpServletRequest request,
+                           HttpServletResponse response, Object obj, ModelAndView mv)
+            throws Exception {
+        // TODO Auto-generated method stub
+        response.setDateHeader("Expires", 0);
+        response.setHeader("Buffer", "True");
+        response.setHeader("Cache-Control", "no-cache");
+        response.setHeader("Expires", "0");
+        response.setHeader("ETag", String.valueOf(System.currentTimeMillis()));
+        response.setHeader("Pragma", "no-cache");
+        response.setHeader("Date", String.valueOf(new Date()));
+        response.setHeader("Last-Modified", String.valueOf(new Date()));
+
+    }
+}

+ 64 - 0
yt-app/app-service/src/main/java/com/ytpm/config/interceptor/PostHttpRequestInterceptor.java

@@ -0,0 +1,64 @@
+package com.ytpm.config.interceptor;
+
+import com.alibaba.fastjson.JSON;
+import com.ytpm.constant.StrConstant;
+import com.ytpm.general.Result;
+import com.ytpm.general.StatusCode;
+import com.ytpm.model.ActiveUser;
+import com.ytpm.model.YtDyzUser;
+import com.ytpm.util.RedisService;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.SecurityUtils;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+
+/**
+ * Post 请求拦截器 记录用户操作行为
+
+ */
+@Slf4j(topic = "请求拦截器")
+@Component
+public class PostHttpRequestInterceptor implements HandlerInterceptor {
+
+    @Autowired
+    private RedisService redisService;
+
+    @Override
+    public boolean preHandle(HttpServletRequest request,
+                             HttpServletResponse response, Object obj) throws Exception {
+        try {   //POST方法记录日志
+            if ("POST".equalsIgnoreCase(request.getMethod())) {
+                ActiveUser activeUser = (ActiveUser) SecurityUtils.getSubject().getPrincipal();
+                String userName = null;
+                String userId = null;
+                String ip = request.getRemoteAddr();
+                String uri = request.getRequestURI();
+                if (activeUser != null) {
+                    YtDyzUser user = activeUser.getUser();
+                    userName = user.getNickName();
+                    userId = user.getUserId();
+                    String redisKey = StrConstant.POST_SUBMIT_TIMES +userId+"_"+uri;
+                    long submitTimes = redisService.incrByExp(redisKey,500);
+                    if(submitTimes>1){
+                        log.error("post   error .....userId={},uri={}",userId,uri);
+                        response.setContentType("application/json;charset=utf-8");
+                        Result responseResult = new Result(StatusCode.ERROR, "操作太频繁,请稍后再试。");
+                        response.getWriter().print(JSON.toJSON(responseResult));
+                        return  false;
+                    }
+                }
+                //TODO 保存用户操作记录
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.error("PostHttpRequestInterceptor error={}", e);
+        }
+        return true;
+    }
+
+
+}

+ 88 - 0
yt-app/app-service/src/main/java/com/ytpm/config/interceptor/UserActionInterceptor.java

@@ -0,0 +1,88 @@
+package com.ytpm.config.interceptor;
+
+import com.ytpm.constant.StrConstant;
+import com.ytpm.general.Result;
+import com.ytpm.model.ActiveUser;
+import com.ytpm.model.YtDyzUser;
+import com.ytpm.util.ShiroFilterUtils;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.web.util.WebUtils;
+import org.springframework.stereotype.Component;
+import org.springframework.web.servlet.HandlerInterceptor;
+import org.springframework.web.servlet.ModelAndView;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+@Slf4j(topic = "用户登录/授权拦截器")
+@Component
+public class UserActionInterceptor implements HandlerInterceptor {
+
+
+    /**
+     * 退出后重定向的地址
+     */
+    private final String kickoutUrl = "/sys/toLogin";
+
+    @Override
+    public void afterCompletion(HttpServletRequest request,
+                                HttpServletResponse response, Object obj, Exception e)
+            throws Exception {
+        // TODO Auto-generated method stub
+//        logger.debug("整个请求完成之后调用。DispatcherServlet视图渲染完成之后。(主要是用于进行资源清理工作)");
+
+    }
+
+    @Override
+    public void postHandle(HttpServletRequest request,
+                           HttpServletResponse response, Object obj, ModelAndView mv)
+            throws Exception {
+        // TODO Auto-generated method stub
+//        logger.debug("请求处理之后调用;在视图渲染之前,controller处理之后。");
+
+    }
+
+    @Override
+    public boolean preHandle(HttpServletRequest request,
+                             HttpServletResponse response, Object obj) throws Exception {
+//        logger.debug("请求到达后台方法之前调用(controller之前)");
+        // 1. SecurityUtils获取session中的用户信息
+        // HttpSession session=request.getSession();
+        try {
+            ActiveUser activeUser = (ActiveUser) SecurityUtils.getSubject().getPrincipal();
+            if (activeUser != null) {
+                YtDyzUser user =activeUser.getUser();
+                request.setAttribute("userId",user.getUserId());
+                return true;
+            }
+            SecurityUtils.getSubject().logout();
+        } catch (Exception e) {
+            e.printStackTrace();
+            log.error("登录拦截器异常url={},e={}", request.getRequestURI(), e);
+        }
+        isAjaxResponse(request, response);
+        return false;
+    }
+
+    private boolean isAjaxResponse(HttpServletRequest request,
+                                   HttpServletResponse response) throws IOException {
+        /**
+         * 判断是否已经踢出
+         * 1.如果是Ajax 访问,那么给予json返回值提示。
+         * 2.如果是普通请求,直接跳转到登录页
+         */
+        //判断是不是Ajax请求s
+        if (ShiroFilterUtils.isAjax(request)) {
+            log.debug(getClass().getName() + ",判断已经踢出,重新登录后生效!");
+            Result responseResult = new Result(StrConstant.LOG_OUT, "重新登录");
+            ShiroFilterUtils.out(response, responseResult);
+        } else {
+            // 重定向
+            WebUtils.issueRedirect(request, response, kickoutUrl);
+        }
+        return false;
+    }
+
+}

+ 300 - 0
yt-app/app-service/src/main/java/com/ytpm/config/shiro/ShiroAutoConfiguration.java

@@ -0,0 +1,300 @@
+package com.ytpm.config.shiro;
+
+import com.ytpm.util.MyRedisManager;
+import lombok.Data;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
+import org.apache.shiro.mgt.SecurityManager;
+import org.apache.shiro.session.mgt.SessionManager;
+import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
+import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.apache.shiro.web.servlet.SimpleCookie;
+import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
+import org.crazycake.shiro.RedisCacheManager;
+import org.crazycake.shiro.RedisManager;
+import org.crazycake.shiro.RedisSessionDAO;
+import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
+import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication.Type;
+import org.springframework.boot.context.properties.ConfigurationProperties;
+import org.springframework.boot.web.servlet.FilterRegistrationBean;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+import org.springframework.web.filter.DelegatingFilterProxy;
+
+import javax.servlet.Filter;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 
+ * @author gkHuang
+ *
+ */
+@Slf4j(topic = "shiro 自动装配")
+@Configuration
+@ConditionalOnWebApplication(type = Type.SERVLET)
+@ConditionalOnClass(value = { SecurityManager.class })
+@ConfigurationProperties(prefix = "shiro")
+@Data
+public class ShiroAutoConfiguration {
+
+	private static final String SHIRO_DIALECT = "shiroDialect";
+	private static final String SHIRO_FILTER = "shiroFilter";
+	private String hashAlgorithmName = "md5";// 加密方式
+	private int hashIterations = 2;// 散列次数
+	private String loginUrl = "/sys/toLogin";// 默认的登录页面
+	private String[] anonUrls;
+	private String logOutUrl;
+	private String[] authcUlrs;
+	@Value("${spring.redis.host}")
+	private static String redisHost;
+	@Value("${spring.redis.port}")
+	private static String redisPort;
+	@Value("${spring.redis.database}")
+	private static int redisDB;
+	@Value("${spring.redis.password}")
+	private static String redisPwd;
+
+	@Autowired
+	private MyRedisManager myRedisManager;
+
+	/**
+	 * 配置shiro的过滤器
+	 *
+	 */
+	@Bean(SHIRO_FILTER)
+	public ShiroFilterFactoryBean shiroFilterFactoryBean(SecurityManager securityManager) {
+		ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();
+		// 设置安全管理器
+		factoryBean.setSecurityManager(securityManager);
+		// 设置未登录的时要跳转的页面
+		factoryBean.setLoginUrl(loginUrl);
+		Map<String, String> filterChainDefinitionMap = new HashMap<>();
+		// 设置放行的路径
+		if (anonUrls != null && anonUrls.length > 0) {
+			for (String anon : anonUrls) {
+				filterChainDefinitionMap.put(anon, "anon");
+			}
+		}
+		// 设置登出的路径
+		if (null != logOutUrl) {
+			filterChainDefinitionMap.put(logOutUrl, "logout");
+		}
+		// 设置拦截的路径
+		if (authcUlrs != null && authcUlrs.length > 0) {
+			for (String authc : authcUlrs) {
+				filterChainDefinitionMap.put(authc, "authc");
+			}
+		}
+		filterChainDefinitionMap.put("/api/v2/**", "anon");
+		filterChainDefinitionMap.put("/doc.html", "anon");
+		filterChainDefinitionMap.put("/v2/api-docs", "anon");
+		filterChainDefinitionMap.put("/configuration/ui", "anon");
+		filterChainDefinitionMap.put("/swagger-resources/**", "anon");
+		filterChainDefinitionMap.put("/configuration/security", "anon");
+		filterChainDefinitionMap.put("/swagger-ui.html", "anon");
+		filterChainDefinitionMap.put("/webjars/**", "anon");
+		filterChainDefinitionMap.put("/swagger-resources/configuration/ui", "anon");
+//		filterChainDefinitionMap.put("/**", "authc");
+
+		Map<String, Filter> filters=new HashMap<>();
+//		filters.put("authc", new ShiroLoginFilter());
+		//配置过滤器
+		factoryBean.setFilters(filters);
+		factoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
+		return factoryBean;
+	}
+
+	/**
+	 * 注册shiro的委托过滤器,相当于之前在web.xml里面配置的
+	 *
+	 * @return
+	 */
+	@Bean
+	public FilterRegistrationBean<DelegatingFilterProxy> delegatingFilterProxy() {
+		FilterRegistrationBean<DelegatingFilterProxy> filterRegistrationBean = new FilterRegistrationBean<DelegatingFilterProxy>();
+		DelegatingFilterProxy proxy = new DelegatingFilterProxy();
+		proxy.setTargetFilterLifecycle(true);
+		proxy.setTargetBeanName(SHIRO_FILTER);
+		filterRegistrationBean.setFilter(proxy);
+		return filterRegistrationBean;
+	}
+
+	/**
+	 *  核心安全事务管理器
+	 * 配置SecurityManager
+	 */
+	@Bean("securityManager")
+	public SecurityManager securityManager() {
+		DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
+		// 设置realm.
+		securityManager.setRealm(userRealm());
+		// 自定义缓存实现 使用redis
+		securityManager.setCacheManager(cacheManager());
+		// 自定义session管理 使用redis
+		securityManager.setSessionManager(sessionManager());
+		return securityManager;
+	}
+
+
+	/**
+	 * cacheManager 缓存 redis实现
+	 * 使用的是shiro-redis开源插件
+	 *
+	 * @return
+	 */
+	public RedisCacheManager cacheManager() {
+		RedisCacheManager redisCacheManager = new RedisCacheManager();
+		redisCacheManager.setRedisManager(redisManager());
+		//redis中针对不同用户缓存
+		redisCacheManager.setPrincipalIdFieldName("id");
+		//用户权限信息缓存时间 秒(12h)
+		redisCacheManager.setExpire(43200);
+
+		return redisCacheManager;
+	}
+
+
+	/**
+	 * 配置shiro redisManager
+	 * 使用的是shiro-redis开源插件
+	 *
+	 * @return
+	 */
+	@Bean
+	public RedisManager redisManager() {
+//		RedisManager redisManager =myRedisManager;
+		RedisManager redisManager = new RedisManager();
+		redisManager.setHost(redisHost+":"+redisPort);
+		redisManager.setDatabase(redisDB);
+		redisManager.setPassword(redisPwd);
+		return redisManager;
+	}
+
+
+
+	/**
+	 * RedisSessionDAO shiro sessionDao层的实现 通过redis
+	 * 使用的是shiro-redis开源插件
+	 */
+	@Bean
+	public RedisSessionDAO redisSessionDAO() {
+		RedisSessionDAO redisSessionDAO = new RedisSessionDAO();
+		redisSessionDAO.setRedisManager(redisManager());
+		redisSessionDAO.setKeyPrefix("YT_SESSION_CACHE_");
+		return redisSessionDAO;
+	}
+
+
+	/**
+	 * 声明凭证匹配器
+	 */
+	@Bean("credentialsMatcher")
+	public HashedCredentialsMatcher hashedCredentialsMatcher() {
+		HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
+		credentialsMatcher.setHashAlgorithmName(hashAlgorithmName);
+		credentialsMatcher.setHashIterations(hashIterations);
+		return credentialsMatcher;
+	}
+
+	/**
+	 * 声明userRealm
+	 */
+	@Bean("userRealm")
+	public UserRealm userRealm() {
+		UserRealm userRealm = new UserRealm();
+		// 注入凭证匹配器
+		userRealm.setCredentialsMatcher(hashedCredentialsMatcher());
+		//启用身份验证缓存,即缓存AuthenticationInfo信息,默认false
+		userRealm.setAuthenticationCachingEnabled(true);
+		//缓存AuthenticationInfo信息的缓存名称 在ehcache-shiro.xml中有对应缓存的配置
+		userRealm.setAuthenticationCacheName("authenticationCache");
+		//启用授权缓存,即缓存AuthorizationInfo信息,默认false
+		userRealm.setAuthorizationCachingEnabled(true);
+		//缓存AuthorizationInfo信息的缓存名称  在ehcache-shiro.xml中有对应缓存的配置
+		userRealm.setAuthorizationCacheName("authorizationCache");
+		return userRealm;
+	}
+
+
+
+	/**
+	 * 配置保存sessionId的cookie
+	 * 注意:这里的cookie 不是上面的记住我 cookie 记住我需要一个cookie session管理 也需要自己的cookie
+	 * 默认为: JSESSIONID 问题: 与SERVLET容器名冲突,重新定义为sid
+	 * @return
+	 */
+	@Bean("sessionIdCookie")
+	public SimpleCookie sessionIdCookie(){
+		//这个参数是cookie的名称
+		SimpleCookie simpleCookie = new SimpleCookie("sid");
+		//setcookie的httponly属性如果设为true的话,会增加对xss防护的安全系数。它有以下特点:
+
+		//setcookie()的第七个参数
+		//设为true后,只能通过http访问,javascript无法访问
+		//防止xss读取cookie
+//		simpleCookie.setHttpOnly(true);
+		simpleCookie.setPath("/");
+		//maxAge=-1表示浏览器关闭时失效此Cookie
+		simpleCookie.setMaxAge(-1);
+		return simpleCookie;
+	}
+
+
+
+	/**
+	 * 配置会话管理器,设定会话超时及保存
+	 * @return
+	 */
+	@Bean("sessionManager")
+	public SessionManager sessionManager() {
+		DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
+		sessionManager.setSessionIdCookie(sessionIdCookie());
+		sessionManager.setSessionDAO(redisSessionDAO());
+		sessionManager.setCacheManager(cacheManager());
+
+		//全局会话超时时间(单位毫秒),默认30分钟  1800000
+		sessionManager.setGlobalSessionTimeout(28800000);//8*60*60*1000 8个小时
+		//是否开启删除无效的session对象  默认为true
+		sessionManager.setDeleteInvalidSessions(true);
+		//是否开启定时调度器进行检测过期session 默认为true
+		sessionManager.setSessionValidationSchedulerEnabled(true);
+		//设置session失效的扫描时间, 清理用户直接关闭浏览器造成的孤立会话 默认为 1个小时
+		//设置该属性 就不需要设置 ExecutorServiceSessionValidationScheduler 底层也是默认自动调用ExecutorServiceSessionValidationScheduler
+		//暂时设置为 5秒 用来测试
+		sessionManager.setSessionValidationInterval(28800000);//8*60*60*1000 8个小时
+		//取消url 后面的 JSESSIONID
+		sessionManager.setSessionIdUrlRewritingEnabled(false);
+		return sessionManager;
+
+	}
+
+
+	/**
+	 * 加入注解的使用,不加入这个注解不生效
+	 * @param securityManager
+	 * @return
+	 */
+	@Bean
+	public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
+		AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
+		authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);
+		return authorizationAttributeSourceAdvisor;
+	}
+	/**
+	 * 加入注解的使用,不加入这个注解不生效
+	 * @param
+	 * @return
+	 */
+	@Bean
+	public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() {
+		DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
+		advisorAutoProxyCreator.setProxyTargetClass(true);
+		return advisorAutoProxyCreator;
+	}
+}

+ 18 - 0
yt-app/app-service/src/main/java/com/ytpm/config/shiro/ShiroLifecycleBeanPostProcessorConfig.java

@@ -0,0 +1,18 @@
+package com.ytpm.config.shiro;
+
+import org.apache.shiro.spring.LifecycleBeanPostProcessor;
+import org.springframework.context.annotation.Bean;
+import org.springframework.context.annotation.Configuration;
+
+@Configuration
+public class ShiroLifecycleBeanPostProcessorConfig {
+
+	/**
+	 * 配置Shiro生命周期处理器
+	 * @return
+	 */
+	@Bean(name = "lifecycleBeanPostProcessor")
+	public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
+		return new LifecycleBeanPostProcessor();
+	}
+}

+ 59 - 0
yt-app/app-service/src/main/java/com/ytpm/config/shiro/UserRealm.java

@@ -0,0 +1,59 @@
+package com.ytpm.config.shiro;
+
+import com.ytpm.model.ActiveUser;
+import com.ytpm.model.YtDyzUser;
+import com.ytpm.service.AppUserService;
+import org.apache.shiro.authc.AuthenticationException;
+import org.apache.shiro.authc.AuthenticationInfo;
+import org.apache.shiro.authc.AuthenticationToken;
+import org.apache.shiro.authc.SimpleAuthenticationInfo;
+import org.apache.shiro.authz.AuthorizationInfo;
+import org.apache.shiro.authz.SimpleAuthorizationInfo;
+import org.apache.shiro.realm.AuthorizingRealm;
+import org.apache.shiro.subject.PrincipalCollection;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.context.annotation.Lazy;
+
+
+//@Service
+public class UserRealm extends AuthorizingRealm {
+
+	@Autowired
+	@Lazy  //只有使用的时候才会加载
+	private AppUserService userService;
+
+	@Override
+	public String getName() {
+		return this.getClass().getSimpleName();
+	}
+
+	/**
+	 * 身份认证 / 登录,验证用户是不是拥有相应的身份;
+	 */
+	@Override
+	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
+		String openid = token.getPrincipal().toString();
+		YtDyzUser user = userService.selectByOpenid(openid);
+		if (null != user) {
+			ActiveUser activeUser = new ActiveUser();
+			activeUser.setUser(user);
+			activeUser.setId(user.getUserId());
+
+			//微信登录没有密码,这里默认使用昵称
+			SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(activeUser, user.getNickName(),
+					this.getName());
+			return info;
+		}
+		return null;
+	}
+
+	/**
+	 * 授权,即权限验证,验证某个已认证的用户是否拥有某个权限;
+	 */
+	@Override
+	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
+		SimpleAuthorizationInfo authorizationInfo=new SimpleAuthorizationInfo();
+		//TODO 用户授权认证
+		return authorizationInfo;
+	}
+}

+ 116 - 13
yt-app/app-service/src/main/java/com/ytpm/controller/WxController.java

@@ -3,28 +3,43 @@ package com.ytpm.controller;
 import cn.hutool.core.util.IdUtil;
 import cn.hutool.http.HttpUtil;
 import com.alibaba.fastjson.JSON;
-import com.ytpm.app.model.YtAppUserLoginRecord;
+import com.ytpm.agent.enums.UserStatusEnum;
+
 import com.ytpm.app.param.WxLoginParam;
 import com.ytpm.app.view.WxDefaultConfig;
 import com.ytpm.app.view.WxLoginResult;
 import com.ytpm.app.view.WxUserInfo;
+import com.ytpm.constant.StrConstant;
+import com.ytpm.dao.AppUserMapper;
 import com.ytpm.dao.LoginRecordMapper;
-import com.ytpm.feign.RiskFeign;
+import com.ytpm.dao.QuestionMapper;
 import com.ytpm.general.RepMessage;
 import com.ytpm.general.Result;
+import com.ytpm.handle.CustomerException;
+import com.ytpm.model.ActiveUser;
+import com.ytpm.model.YtDyzLoginRecord;
+import com.ytpm.model.YtDyzPowerRecord;
+import com.ytpm.model.YtDyzUser;
+import com.ytpm.util.ShiroSubjectUtil;
+import com.ytpm.util.WebUtils;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
 import lombok.extern.slf4j.Slf4j;
-import org.apache.ibatis.annotations.Param;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.authc.UsernamePasswordToken;
+import org.apache.shiro.subject.Subject;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
+import org.springframework.transaction.annotation.Transactional;
 import org.springframework.web.bind.annotation.GetMapping;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
 import org.springframework.web.bind.annotation.RestController;
 
 import java.util.Date;
+import java.util.Objects;
 
 
 @Slf4j
@@ -38,43 +53,131 @@ public class WxController {
     private  String SECRET;
     private final static String GRANT_TYPE = "authorization_code";
 
+    @Autowired
+    private AppUserMapper appUserMapper;
     @Autowired
     private LoginRecordMapper loginRecordMapper;
     @Autowired
-    private RiskFeign riskFeign;
+    private QuestionMapper questionMapper;
 
     @PostMapping("/login")
     @ApiOperation("微信登录")
-    public Result<WxUserInfo> wxLogin(@RequestBody WxLoginParam param) {
+    @Transactional(rollbackFor = Exception.class)
+    public Result<YtDyzUser> wxLogin(@RequestBody WxLoginParam param) {
         //拿到授权码 请求微信登录返回access_token
         String wxLoginUrl = "https://api.weixin.qq.com/sns/oauth2/access_token?appid="+APP_ID+"&secret="+SECRET+"&code="+param.getWxCode()+"&grant_type="+GRANT_TYPE;
         String result = HttpUtil.get(wxLoginUrl);
         WxLoginResult loginResult = JSON.parseObject(result, WxLoginResult.class);
+        log.error("授权码获取的登录结果:{}",loginResult);
         // TODO 拿到openid 调用风控服务过审,不满足风控要求则抛出异常
-//        riskFeign.checkUser(loginResult.getOpenid());
         // 根据token和openid 获取用户信息
         String userInfoUrl = "https://api.weixin.qq.com/sns/userinfo?access_token="+loginResult.getAccess_token()+"&openid="+loginResult.getOpenid()+"&lang=zh_CN";
         String curUser = HttpUtil.get(userInfoUrl);
         WxUserInfo wxUserInfo = JSON.parseObject(curUser, WxUserInfo.class);
+        log.error("获取的用户信息:{}",wxUserInfo);
+        if(Objects.isNull(wxUserInfo)) {
+            throw new CustomerException("微信用户登录失败");
+        }
+        //查询用户表是否存在该用户,不存在则注册保存用户信息
+        YtDyzUser old = appUserMapper.getYtAppUser(loginResult.getOpenid());
+        if(Objects.nonNull(old)){
+//            ShiroAuth(wxUserInfo);//Shiro 登录逻辑
+            YtDyzUser newUser = new YtDyzUser();
+            newUser.setNickName(wxUserInfo.getNickname());
+            newUser.setHeadImg(wxUserInfo.getHeadimgurl());
+            newUser.setLastLoginTime(new Date());
+            newUser.setLastLoginIp(param.getLoginIp());
+            appUserMapper.updateUser(newUser);
+        }else{
+            registryUser(param,wxUserInfo,loginResult);
+        }
         // 添加用户登录记录
-        YtAppUserLoginRecord loginRecord = new YtAppUserLoginRecord();
-        loginRecord.setAppId(APP_ID);
+        addLoginRecord(wxUserInfo,param);
+        //设置最后一次答题问题ID、今日答题数、历史答题数
+        old.setNickName(wxUserInfo.getNickname());
+        setExtInfo(old,wxUserInfo.getHeadimgurl());
+        return Result.resultOk(RepMessage.LOGIN_SUCCESS, old);
+    }
+
+    /**
+     * Shiro 认证登录
+     */
+    private void ShiroAuth(WxUserInfo wxUserInfo) {
+        //获取当前用户Subject实例
+        Subject subject = SecurityUtils.getSubject();
+        UsernamePasswordToken token = new UsernamePasswordToken(wxUserInfo.getOpenid(), wxUserInfo.getNickname());
+        if(!subject.isAuthenticated()){
+            subject.login(token);
+            ActiveUser activeUser = (ActiveUser) subject.getPrincipal();
+            ShiroSubjectUtil.loginOut(activeUser.getUser());
+            WebUtils.getSession().setAttribute("user", activeUser.getUser());
+        }
+    }
+
+    /**
+     * 设置扩展信息
+     */
+    private void setExtInfo(YtDyzUser old, String headimgurl) {
+        old.setHeadImg(headimgurl);
+        old.setLastQuestionId(questionMapper.getLastQuestionId(old.getUserId()));
+        old.setTodayAnswerCount(questionMapper.getAnswerCount(old.getUserId(),1));
+        old.setHistoryAnswerCount(questionMapper.getAnswerCount(old.getUserId(),2));
+        old.setAnswerRecordList(questionMapper.getAnswerRecords(old.getUserId()));
+    }
+
+    /**
+     * 增加用户登录记录
+     */
+    private void addLoginRecord(WxUserInfo wxUserInfo, WxLoginParam param) {
+        YtDyzLoginRecord loginRecord = new YtDyzLoginRecord();
         loginRecord.setRecordId(IdUtil.fastSimpleUUID());
         loginRecord.setUserId(wxUserInfo.getOpenid());
         loginRecord.setLoginTime(new Date());
-        loginRecord.setPhoneBrand(param.getBrand());
-        loginRecord.setPhoneModel(param.getModel());
+        loginRecord.setDeviceBrand(param.getBrand());
+        loginRecord.setDeviceModel(param.getModel());
         loginRecord.setLoginIp(param.getLoginIp());
-        loginRecord.setCommunicationOperator(param.getIpOperator());
+        loginRecord.setOperator(param.getIpOperator());
         loginRecord.setIpAddr(param.getLoginIp());
         loginRecordMapper.insertOne(loginRecord);
-        return Result.resultOk(RepMessage.LOGIN_SUCCESS,wxUserInfo);
+    }
+
+    /**
+     * 注册用户
+     */
+    private void registryUser(WxLoginParam param,WxUserInfo wxUserInfo,WxLoginResult loginResult) {
+        YtDyzUser old =  new YtDyzUser();
+        old.setUserId(IdUtil.fastSimpleUUID());
+        old.setNickName(wxUserInfo.getNickname());
+        old.setLastLoginTime(new Date());
+        old.setRegistryTime(new Date());
+        old.setLastLoginIp(param.getLoginIp());
+        old.setLoginDays(1);
+        old.setPower(0);
+        old.setUserStatus(UserStatusEnum.NORMAL.getCode());
+        old.setWxOpenId(loginResult.getOpenid());
+        old.setHeadImg(wxUserInfo.getHeadimgurl());
+        old.setPlatformId(StrConstant.PLATFORM_ID_PREFIX + IdUtil.getSnowflakeNextIdStr());
+        appUserMapper.addOne(old);
     }
 
     @ApiOperation("获取微信默认配置项")
     @GetMapping("/defaultConfig")
     public Result<WxDefaultConfig> getWxDefaultConfig() {
-        return Result.resultObjOk(new WxDefaultConfig(APP_ID,SECRET)) ;
+        return Result.resultObjOk(new WxDefaultConfig(APP_ID, SECRET));
     }
 
+    @ApiOperation("体力增加")
+    @GetMapping("/addPower")
+    @Transactional(rollbackFor = Exception.class)
+    public Result<YtDyzUser> addPower(@RequestParam("userId")String userId) {
+        appUserMapper.addOnePower(userId);
+        YtDyzPowerRecord record = new YtDyzPowerRecord();
+        record.setUserId(userId);
+        record.setRecordId(IdUtil.fastSimpleUUID());
+        record.setAddTime(new Date());
+        record.setType(1);
+        record.setRemark("增加体力");
+        appUserMapper.addPowerRecord(record);
+        return Result.resultOk(RepMessage.ADD_SUCCESS);
+    }
 }

+ 0 - 14
yt-app/app-service/src/main/java/com/ytpm/dao/AgentUserMapper.java

@@ -1,14 +0,0 @@
-package com.ytpm.dao;
-
-import com.ytpm.agent.view.AgentUserInfo;
-import org.apache.ibatis.annotations.Param;
-import org.mapstruct.Mapper;
-
-@Mapper
-public interface AgentUserMapper {
-    /**
-     * 获取当前登录用户信息
-     * @param loginName 用户名
-     */
-    AgentUserInfo getCurrentUserInfo(@Param("loginName")String loginName);
-}

+ 39 - 0
yt-app/app-service/src/main/java/com/ytpm/dao/AppUserMapper.java

@@ -0,0 +1,39 @@
+package com.ytpm.dao;
+
+import com.ytpm.model.YtDyzPowerRecord;
+import com.ytpm.model.YtDyzUser;
+import org.apache.ibatis.annotations.Param;
+import org.mapstruct.Mapper;
+
+@Mapper
+public interface AppUserMapper {
+
+    /**
+     * openid查询用户信息
+     */
+    YtDyzUser getYtAppUser(@Param("openid")String openid);
+
+    /**
+     * 新增应用用户
+     */
+    void addOne(YtDyzUser user);
+
+    /**
+     * 增加体力
+     */
+    void addOnePower(@Param("userId")String userId);
+    /**
+     * 减少体力
+     */
+    void subOnePower(@Param("userId")String userId);
+
+    /**
+     * 体力增加记录
+     */
+    void addPowerRecord(YtDyzPowerRecord record);
+
+    /**
+     * 修改用户信息
+     */
+    void updateUser(YtDyzUser newUser);
+}

+ 2 - 2
yt-app/app-service/src/main/java/com/ytpm/dao/LoginRecordMapper.java

@@ -1,6 +1,6 @@
 package com.ytpm.dao;
 
-import com.ytpm.app.model.YtAppUserLoginRecord;
+import com.ytpm.model.YtDyzLoginRecord;
 import org.mapstruct.Mapper;
 
 @Mapper
@@ -8,5 +8,5 @@ public interface LoginRecordMapper {
     /**
      * 增加用户登录记录
      */
-    void insertOne(YtAppUserLoginRecord loginRecord);
+    void insertOne(YtDyzLoginRecord loginRecord);
 }

+ 16 - 0
yt-app/app-service/src/main/java/com/ytpm/dao/QuestionMapper.java

@@ -20,4 +20,20 @@ public interface QuestionMapper {
      * 回答问题
      */
     void saveAnswerRecord(YtDyzAnswerRecord record);
+
+    /**
+     * 获取最后一次的问题ID
+     */
+    String getLastQuestionId(@Param("userId") String userId);
+
+    /**
+     * 获取答题数
+     * @param type 1-今日 2-历史
+     */
+    Integer getAnswerCount(@Param("userId")String userId, @Param("type") int type);
+
+    /**
+     * 查询答题历史记录
+     */
+    List<YtDyzAnswerRecord> getAnswerRecords(@Param("userId") String userId);
 }

+ 28 - 0
yt-app/app-service/src/main/java/com/ytpm/model/ActiveUser.java

@@ -0,0 +1,28 @@
+package com.ytpm.model;
+
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.io.Serializable;
+import java.util.List;
+
+/**
+ * 
+ * @author gkHuang
+ *
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class ActiveUser implements Serializable {
+
+	private YtDyzUser user;
+
+	private String id;
+
+	private List<String> roles;
+	
+	private List<String> permissions;
+
+}

+ 30 - 0
yt-app/app-service/src/main/java/com/ytpm/model/YtDyzLoginRecord.java

@@ -0,0 +1,30 @@
+package com.ytpm.model;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+import java.util.Date;
+
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class YtDyzLoginRecord {
+    /** 登录记录ID */
+    private String recordId;
+    /** 用户ID */
+    private String userId;
+    /** 登录时间 */
+    private Date loginTime;
+    /** 设备品牌 */
+    private String deviceBrand;
+    /** 设备型号 */
+    private String deviceModel;
+    /** 登录IP */
+    private String loginIp;
+    /** 运营商 */
+    private String operator;
+    /** IP归属地 */
+    private String ipAddr;
+}

+ 15 - 0
yt-app/app-service/src/main/java/com/ytpm/model/YtDyzPowerRecord.java

@@ -0,0 +1,15 @@
+package com.ytpm.model;
+
+import lombok.Data;
+
+import java.util.Date;
+
+@Data
+public class YtDyzPowerRecord {
+
+    private String recordId;
+    private String userId;
+    private Integer type;
+    private String remark;
+    private Date addTime;
+}

+ 96 - 0
yt-app/app-service/src/main/java/com/ytpm/model/YtDyzUser.java

@@ -0,0 +1,96 @@
+package com.ytpm.model;
+
+import com.ytpm.app.model.YtDyzAnswerRecord;
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.NoArgsConstructor;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Date;
+import java.util.List;
+
+/**
+ * 答题王用户表
+ */
+@Getter
+@Setter
+@NoArgsConstructor
+@AllArgsConstructor
+@ApiModel("用户信息")
+public class YtDyzUser {
+    /** 用户ID */
+    @ApiModelProperty("用户ID")
+    private String userId;
+    /** 用户昵称 */
+    @ApiModelProperty("用户昵称")
+    private String nickName;
+    /** 用户头像 */
+    @ApiModelProperty("用户头像")
+    private String headImg;
+    /** 注册时间 */
+    @ApiModelProperty("注册时间")
+    private Date registryTime;
+    /** 最新登录时间 */
+    @ApiModelProperty("最新登录时间")
+    private Date lastLoginTime;
+    /** 最新登录IP */
+    @ApiModelProperty("最新登录IP")
+    private String lastLoginIp;
+    /** 登录天数 */
+    @ApiModelProperty("登录天数")
+    private Integer loginDays;
+    /** 总观看视频数 */
+    @ApiModelProperty("总观看视频数")
+    private String totalVideo;
+    /** 总收益 */
+    @ApiModelProperty("总收益")
+    private BigDecimal totalIncome;
+    /** 红包余额 */
+    @ApiModelProperty("红包余额")
+    private BigDecimal redPacketBalance;
+    /** 红包总金额 */
+    @ApiModelProperty("红包总金额")
+    private BigDecimal redPacketAmount;
+    /** 积分余额 */
+    @ApiModelProperty("积分余额")
+    private BigDecimal pointsBalance;
+    /** 积分总额 */
+    @ApiModelProperty("积分总额")
+    private BigDecimal pointsTotal;
+    /** 提现总额 */
+    @ApiModelProperty("提现总额")
+    private BigDecimal withdrawTotal;
+    /** 用户签到天数 */
+    @ApiModelProperty("用户签到天数")
+    private Integer signDays;
+    /** 用户状态 */
+    @ApiModelProperty("用户状态")
+    private Integer userStatus;
+    /** 风控原因 */
+    @ApiModelProperty("风控原因")
+    private String riskReason;
+    /** 微信openid */
+    @ApiModelProperty("微信openid")
+    private String wxOpenId;
+    /** 平台ID 唯一标识 */
+    @ApiModelProperty("平台ID")
+    private String platformId;
+    /** 最后一次回答问题ID */
+    @ApiModelProperty("最后一次回答问题ID")
+    private String lastQuestionId;
+    /** 体力 */
+    @ApiModelProperty("体力")
+    private Integer power;
+    /** 今日答题数 */
+    @ApiModelProperty("今日答题数")
+    private Integer todayAnswerCount;
+    /** 历史答题数 */
+    @ApiModelProperty("历史答题数")
+    private Integer historyAnswerCount;
+    /** 答题历史记录 */
+    @ApiModelProperty("答题历史记录")
+    private List<YtDyzAnswerRecord> answerRecordList;
+}

+ 10 - 0
yt-app/app-service/src/main/java/com/ytpm/service/AppUserService.java

@@ -0,0 +1,10 @@
+package com.ytpm.service;
+
+import com.ytpm.model.YtDyzUser;
+
+public interface AppUserService {
+    /**
+     * openid查询用户信息
+     */
+    YtDyzUser selectByOpenid(String openid);
+}

+ 22 - 0
yt-app/app-service/src/main/java/com/ytpm/service/impl/AppUserServiceImpl.java

@@ -0,0 +1,22 @@
+package com.ytpm.service.impl;
+
+import com.ytpm.dao.AppUserMapper;
+import com.ytpm.model.YtDyzUser;
+import com.ytpm.service.AppUserService;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+@Service
+public class AppUserServiceImpl implements AppUserService {
+
+    @Autowired
+    private AppUserMapper appUserMapper;
+
+    /**
+     * openid查询用户信息
+     */
+    @Override
+    public YtDyzUser selectByOpenid(String openid) {
+        return appUserMapper.getYtAppUser(openid);
+    }
+}

+ 14 - 0
yt-app/app-service/src/main/java/com/ytpm/service/impl/QuestionServiceImpl.java

@@ -6,12 +6,15 @@ import com.github.pagehelper.PageInfo;
 import com.ytpm.app.model.YtDyzAnswerRecord;
 import com.ytpm.app.param.AnswerRecordParam;
 import com.ytpm.app.view.QuestionListView;
+import com.ytpm.dao.AppUserMapper;
 import com.ytpm.dao.QuestionMapper;
 import com.ytpm.general.RepMessage;
 import com.ytpm.general.Result;
 import com.ytpm.general.ResultTable;
+import com.ytpm.model.YtDyzPowerRecord;
 import com.ytpm.service.QuestionService;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 import javax.annotation.Resource;
 import java.util.Date;
@@ -21,6 +24,8 @@ public class QuestionServiceImpl implements QuestionService {
 
     @Resource
     private QuestionMapper questionMapper;
+    @Resource
+    private AppUserMapper appUserMapper;
 
     /**
      * 获取题库
@@ -33,12 +38,21 @@ public class QuestionServiceImpl implements QuestionService {
      * 回答问题
      */
     @Override
+    @Transactional(rollbackFor = Exception.class)
     public Result<String> answerQuestion(AnswerRecordParam param) {
         YtDyzAnswerRecord record = new YtDyzAnswerRecord();
         BeanUtil.copyProperties(param,record);
         record.setRecordId(IdUtil.fastSimpleUUID());
         record.setAnswerTime(new Date());
         questionMapper.saveAnswerRecord(record);
+        appUserMapper.subOnePower(param.getUserId());
+        YtDyzPowerRecord powerRecord = new YtDyzPowerRecord();
+        powerRecord.setUserId(param.getUserId());
+        powerRecord.setRecordId(IdUtil.fastSimpleUUID());
+        powerRecord.setAddTime(new Date());
+        powerRecord.setType(1);
+        powerRecord.setRemark("减少体力");
+        appUserMapper.addPowerRecord(powerRecord);
         return Result.resultOk(RepMessage.SAVE_SUCCESS);
     }
 }

+ 41 - 0
yt-app/app-service/src/main/java/com/ytpm/util/MyRedisManager.java

@@ -0,0 +1,41 @@
+package com.ytpm.util;
+
+import org.crazycake.shiro.RedisManager;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import java.util.Base64;
+
+/**
+ *  单独封装redisManager
+ * @Author :  LeeM
+ * @Date :  2020/7/15   11:15
+ */
+@Component
+public class MyRedisManager extends RedisManager {
+
+    @Autowired
+    RedisService redisService;
+
+
+    @Override
+    public byte[] set(byte[] key, byte[] value, int expire) {
+        String val = Base64.getEncoder().encodeToString(value);
+        expire=12000;
+        redisService.setTimeOutStr(new String(key),val,expire);
+        return value;
+    }
+
+
+    @Override
+    public byte[] get(byte[] key){
+        String s = redisService.getStr(new String(key));
+        if (s == null){
+            return null;
+        }
+        return Base64.getDecoder().decode(s);
+    }
+
+
+
+}

+ 71 - 0
yt-app/app-service/src/main/java/com/ytpm/util/ShiroFilterUtils.java

@@ -0,0 +1,71 @@
+package com.ytpm.util;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.ytpm.general.Result;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.servlet.ServletRequest;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import java.io.PrintWriter;
+
+import com.ytpm.model.ActiveUser;
+/**
+ * 
+ * @项目名称:zld-xdxt
+ * @类名称:ShiroFilterUtils
+ * @类描述:shiro工具类
+ * @创建人:deng.qj
+ * @创建时间:2020-07-07 13:33
+ * @version:
+ */
+public class ShiroFilterUtils {
+	private static final Logger logger = LoggerFactory
+			.getLogger(ShiroFilterUtils.class);
+	private final static ObjectMapper objectMapper = new ObjectMapper();
+    /**
+     * 
+     * @描述:判断请求是否是ajax
+     * @创建人:wyait
+     * @创建时间:2018年4月24日 下午5:00:22
+     * @param request
+     * @return
+     */
+    public static boolean isAjax(ServletRequest request){
+    	String header = ((HttpServletRequest) request).getHeader("X-Requested-With");
+    	if("XMLHttpRequest".equalsIgnoreCase(header)){
+    		logger.debug("shiro工具类【zld-xdxt-->ShiroFilterUtils.isAjax】当前请求,为Ajax请求");
+    		return Boolean.TRUE;
+    	}
+    	logger.debug("shiro工具类【zld-xdxt-->ShiroFilterUtils.isAjax】当前请求,非Ajax请求");
+    	return Boolean.FALSE;
+    }
+
+	/**
+	 *
+	 * @描述:response输出json
+	 * @创建人:wyait
+	 * @创建时间:2018年4月24日 下午5:14:22
+	 * @param response
+	 * @param result
+	 */
+	public static void out(HttpServletResponse response, Result result){
+		PrintWriter out = null;
+		try {
+			response.setCharacterEncoding("UTF-8");//设置编码
+			response.setContentType("application/json");//设置返回类型
+			out = response.getWriter();
+			out.println(objectMapper.writeValueAsString(result));//输出
+			logger.error("用户登出提示");
+		} catch (Exception e) {
+			logger.error("用户登出提示信息出错", e);
+		}finally{
+			if(null != out){
+				out.flush();
+				out.close();
+			}
+		}
+	}
+
+}

+ 58 - 0
yt-app/app-service/src/main/java/com/ytpm/util/ShiroSubjectUtil.java

@@ -0,0 +1,58 @@
+package com.ytpm.util;
+
+import com.ytpm.model.ActiveUser;
+import com.ytpm.model.YtDyzUser;
+import org.apache.shiro.SecurityUtils;
+import org.apache.shiro.session.Session;
+import org.apache.shiro.subject.Subject;
+import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
+import org.apache.shiro.web.session.mgt.DefaultWebSessionManager;
+
+import java.util.Collection;
+
+/**
+ * Shiro 身份信息
+ */
+public class ShiroSubjectUtil {
+
+    /**
+     * 获取当前登录的用户
+     * @return
+     */
+    public static YtDyzUser getLoginUser(){
+        Subject subject = SecurityUtils.getSubject();
+        ActiveUser activeUser = (ActiveUser) subject.getPrincipal();
+        YtDyzUser user = activeUser.getUser();
+        return user;
+    }
+
+    /**
+     * 获取当前登录的用户ID
+     * 也可直接使用 request.getAttribute("userId")
+     * @return
+     */
+    public static String getLoginUserId(){
+        Subject subject = SecurityUtils.getSubject();
+        ActiveUser activeUser = (ActiveUser) subject.getPrincipal();
+        YtDyzUser user = activeUser.getUser();
+        return user.getUserId();
+    }
+
+    /**
+     * 让指定用户退出登录
+     * @param user
+     */
+    public static void loginOut(YtDyzUser user){
+        //处理session
+        DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
+        DefaultWebSessionManager sessionManager = (DefaultWebSessionManager)securityManager.getSessionManager();
+        Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();//获取当前已登录的用户session列表
+        for(Session session:sessions) {
+            //清除该用户以前登录时保存的session
+            if (user.equals(session.getAttribute("user"))){
+                sessionManager.getSessionDAO().delete(session);
+            }
+        }
+    }
+
+}

+ 29 - 0
yt-app/app-service/src/main/java/com/ytpm/util/WebUtils.java

@@ -0,0 +1,29 @@
+package com.ytpm.util;
+
+import org.springframework.web.context.request.RequestContextHolder;
+import org.springframework.web.context.request.ServletRequestAttributes;
+
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpSession;
+
+public class WebUtils {
+	
+	
+	/**
+	 * 得到requset
+	 */
+	public static HttpServletRequest getRequest() {
+		ServletRequestAttributes requestAttributes = (ServletRequestAttributes) 
+				RequestContextHolder.getRequestAttributes();
+		HttpServletRequest request = requestAttributes.getRequest();
+		return request;
+	}
+	
+	/**
+	 * 得到session
+	 */
+	public static HttpSession getSession() {
+		return getRequest().getSession();
+	}
+
+}

+ 0 - 12
yt-app/app-service/src/main/resources/mapper/AgentUserMapper.xml

@@ -1,12 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" ?>
-<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
-<mapper namespace="com.ytpm.dao.AgentUserMapper">
-
-    <select id="getCurrentUserInfo" resultType="com.ytpm.agent.view.AgentUserInfo">
-        select
-            user_id, nick_name, head_image, login_name, encrypt_pwd, salt, phone, last_login_time, last_login_ip, phone_brand, phone_model, account_status, channel_id, user_type, login_days, total_income, app_id, registry_time, transfer_amount
-        from yt_platform_user
-        where account_status = 1
-        and login_name = #{loginName}
-    </select>
-</mapper>

+ 86 - 0
yt-app/app-service/src/main/resources/mapper/AppUserMapper.xml

@@ -0,0 +1,86 @@
+<?xml version="1.0" encoding="UTF-8" ?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.ytpm.dao.AppUserMapper">
+    <insert id="addOne" parameterType="com.ytpm.model.YtDyzUser">
+        insert into yt_dyz_user
+        (
+         user_id,
+         nick_name,
+         head_img,
+         registry_time,
+         last_login_time,
+         last_login_ip,
+         login_days,
+         total_video,
+         total_income,
+         red_packet_balance,
+         red_packet_amount,
+         points_balance,
+         points_total,
+         withdraw_total,
+         sign_days,
+         user_status,
+         risk_reason,
+         wx_open_id,
+         platform_id,
+         power
+        )
+        values
+        (
+         #{userId},
+         #{nickName},
+         #{headImg},
+         #{registryTime},
+         #{lastLoginTime},
+         #{lastLoginIp},
+         #{loginDays},
+         #{totalVideo},
+         #{totalIncome},
+         #{redPacketBalance},
+         #{redPacketAmount},
+         #{pointsBalance},
+         #{pointsTotal},
+         #{withdrawTotal},
+         #{signDays},
+         #{userStatus},
+         #{riskReason},
+         #{wxOpenId},
+         #{platformId},
+         #{power}
+        )
+    </insert>
+    <insert id="addPowerRecord">
+        insert into yt_dyz_power_record
+        (
+         record_id, user_id, type, remark, add_time
+        )
+        values
+        (
+         #{recordId},#{userId},#{type},#{remark},#{addTime}
+        )
+    </insert>
+    <update id="addOnePower">
+        update yt_dyz_user set power = power+1 where user_id = #{userId}
+    </update>
+    <update id="subOnePower">
+        update yt_dyz_user set power = power-1 where user_id = #{userId}
+    </update>
+    <update id="updateUser">
+        update yt_dyz_user
+        <set>
+            <if test="nickName != null">
+                nick_name = #{nickName},
+            </if>
+            <if test="headImg != null">
+                head_img = #{headImg}
+            </if>
+        </set>
+        where user_id = #{userId}
+    </update>
+    <select id="getYtAppUser" resultType="com.ytpm.model.YtDyzUser">
+        select
+           user_id, nick_name,head_img, power, registry_time, last_login_time, last_login_ip, login_days, total_video, total_income, red_packet_balance, red_packet_amount, points_balance, points_total, withdraw_total, sign_days, user_status, risk_reason, wx_open_id, platform_id
+        from yt_dyz_user
+        where wx_open_id = #{openid}
+    </select>
+</mapper>

+ 8 - 10
yt-app/app-service/src/main/resources/mapper/LoginRecordMapper.xml

@@ -3,29 +3,27 @@
 <mapper namespace="com.ytpm.dao.LoginRecordMapper">
 
     <insert id="insertOne">
-        insert into yt_app_user_login_record
+        insert into yt_dyz_login_record
         (
          record_id,
          user_id,
-         app_id,
          login_time,
-         phone_brand,
-         phone_model,
+         device_brand,
+         device_model,
          login_ip,
-         communication_operator,
+         operator,
          ip_addr
         )
         values
         (
          #{recordId},
          #{userId},
-         #{appId},
          #{loginTime},
-         #{phoneBrand},
-         #{phoneModel},
+         #{deviceBrand},
+         #{deviceModel},
          #{loginIp},
-         #{communicationOperator},
+         #{operator},
          #{ipAddr}
-        )
+         );
     </insert>
 </mapper>

+ 23 - 0
yt-app/app-service/src/main/resources/mapper/QuestionMapper.xml

@@ -33,4 +33,27 @@
         ON ydq.question_id = ydqi.question_id
         where app_id = #{appId}
     </select>
+    <select id="getLastQuestionId" resultType="java.lang.String">
+        select
+            question_id
+        from yt_dyz_answer_record
+        where user_id = #{userId}
+        order by answer_time desc limit 1
+    </select>
+    <select id="getAnswerCount" resultType="java.lang.Integer">
+        select
+            count(*)
+        from yt_dyz_answer_record
+        where user_id = #{userId}
+        <if test="type != null and type == 1">
+            and DATE_FORMAT(answer_time, '%Y-%m-%d') = current_date()
+        </if>
+    </select>
+    <select id="getAnswerRecords" resultType="com.ytpm.app.model.YtDyzAnswerRecord">
+        select
+            record_id, question_id, item_id, duration, answer_time, user_id
+        from yt_dyz_answer_record
+        where user_id = #{userId}
+        order by answer_time desc
+    </select>
 </mapper>

+ 1 - 0
yt-app/pom.xml

@@ -15,6 +15,7 @@
     <url>http://maven.apache.org</url>
     <modules>
         <module>app-service</module>
+        <module>app-feign</module>
     </modules>
 
     <properties>

+ 31 - 0
yt-common/src/main/java/com/ytpm/advertise/param/UnitsItemParam.java

@@ -0,0 +1,31 @@
+package com.ytpm.advertise.param;
+
+import com.ytpm.advertise.view.UnitsAdSourceView;
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+@Data
+@ApiModel("广告源信息项入参")
+public class UnitsItemParam {
+    /** 广告源ID */
+    private Integer id;
+    /** 广告源名称 */
+    private String name;
+    /** Taku广告平台账号ID */
+    private String network_id;
+    /** 广告源类型
+     2:常规广告源
+     10:兜底广告源
+     12:客户端竞价广告源
+     13:服务端竞价广告源 */
+    private String type;
+    /** -1: 非混合类型
+     0:混合native类型
+     1:混合rewarded_video类型
+     2:混合banner类型
+     3:混合interstitial类型
+     4:混合splash类型 */
+    private String mix_format;
+    /** 广告源配置参数 */
+    private UnitsAdSourceView adsource_token;
+}

+ 26 - 0
yt-common/src/main/java/com/ytpm/advertise/param/UnitsListParam.java

@@ -0,0 +1,26 @@
+package com.ytpm.advertise.param;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import javax.validation.constraints.Max;
+import javax.validation.constraints.Size;
+import java.util.List;
+
+@Data
+public class UnitsListParam {
+    @Size(max = 100)
+    @ApiModelProperty(value = "Taku应用ID列表")
+    private List<String> app_ids;
+    @Size(max = 100)
+    @ApiModelProperty(value = "Taku广告位ID列表")
+    private List<String> placement_ids;
+    @Size(max = 100)
+    @ApiModelProperty(value = "Taku三方平台账号ID列表")
+    private List<String> network_ids;
+    @ApiModelProperty(value = "起始偏移量,默认0")
+    private Integer start;
+    @Max(value = 1000)
+    @ApiModelProperty(value = "获取个数")
+    private Integer limit;
+}

+ 15 - 0
yt-common/src/main/java/com/ytpm/advertise/param/UnitsParam.java

@@ -0,0 +1,15 @@
+package com.ytpm.advertise.param;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@ApiModel("广告源入参")
+public class UnitsParam {
+    /** Taku的广告位ID */
+    private String placement_id;
+    /** 广告源信息列表 */
+    private List<UnitsItemParam> items;
+}

+ 14 - 0
yt-common/src/main/java/com/ytpm/advertise/view/SaveItemsView.java

@@ -0,0 +1,14 @@
+package com.ytpm.advertise.view;
+
+import io.swagger.annotations.ApiModelProperty;
+
+public class SaveItemsView {
+    @ApiModelProperty("广告源ID")
+    private Integer id;
+    @ApiModelProperty("错误item所在的索引,从0开始")
+    private Integer index;
+    @ApiModelProperty("错误码")
+    private Integer err_code;
+    @ApiModelProperty("错误信息")
+    private Integer err_msg;
+}

+ 17 - 0
yt-common/src/main/java/com/ytpm/advertise/view/UnitsAdSourceView.java

@@ -0,0 +1,17 @@
+package com.ytpm.advertise.view;
+
+import lombok.Data;
+
+/**
+ * 不同广告平台参数不一
+ */
+@Data
+public class UnitsAdSourceView {
+    /** Tencent 穿山甲  百度 快手 Sigmob */
+    private String app_id;
+    /** 快手  */
+    private String app_name;
+    private String slot_id;
+    /** 穿山甲 */
+    private String personalized_template;
+}

+ 15 - 0
yt-common/src/main/java/com/ytpm/advertise/view/UnitsAddResponse.java

@@ -0,0 +1,15 @@
+package com.ytpm.advertise.view;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@ApiModel("保存广告源返回数据")
+public class UnitsAddResponse {
+    /** 成功的广告源信息列表 */
+    private List<SaveItemsView> items;
+    /** 错误广告源信息列表 */
+    private List<ResponseErrors> errors;
+}

+ 22 - 0
yt-common/src/main/java/com/ytpm/advertise/view/UnitsItemsView.java

@@ -0,0 +1,22 @@
+package com.ytpm.advertise.view;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+@ApiModel("广告源列表")
+public class UnitsItemsView {
+    @ApiModelProperty("广告源ID")
+    private Integer id;
+    @ApiModelProperty("广告源名称")
+    private String name;
+    @ApiModelProperty("Taku的应用ID")
+    private String app_id;
+    @ApiModelProperty("Taku的广告位ID")
+    private String placement_id;
+    @ApiModelProperty("Taku广告平台账号ID")
+    private Integer network_id;
+    @ApiModelProperty("广告平台ID")
+    private Integer nw_firm_id;
+}

+ 16 - 0
yt-common/src/main/java/com/ytpm/advertise/view/UnitsListView.java

@@ -0,0 +1,16 @@
+package com.ytpm.advertise.view;
+
+import io.swagger.annotations.ApiModel;
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@ApiModel("广告源管理")
+public class UnitsListView {
+    @ApiModelProperty("搜索条件下的总数")
+    private Integer total;
+    @ApiModelProperty("广告源信息列表")
+    private List<UnitsItemsView> items;
+}

+ 13 - 0
yt-common/src/main/java/com/ytpm/advertise/view/UnitsUpdateResponse.java

@@ -0,0 +1,13 @@
+package com.ytpm.advertise.view;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+import java.util.List;
+
+@Data
+@ApiModel("修改广告源返回数据")
+public class UnitsUpdateResponse {
+    /** 成功的广告源信息列表 */
+    private List<SaveItemsView> items;
+}

+ 18 - 0
yt-common/src/main/java/com/ytpm/advertise/view/UnitsView.java

@@ -0,0 +1,18 @@
+package com.ytpm.advertise.view;
+
+import io.swagger.annotations.ApiModel;
+import lombok.Data;
+
+@Data
+@ApiModel("广告位详情")
+public class UnitsView {
+    private Integer id;
+    private String name;
+    private Integer network_id;
+    private String placement_id;
+    private Integer type;
+    private Integer mix_format;
+    private UnitsAdSourceView adsource_token;
+    private Integer auto_unit_sw;
+    private Integer nw_firm_id;
+}

+ 30 - 0
yt-common/src/main/java/com/ytpm/app/view/YtAppListView.java

@@ -0,0 +1,30 @@
+package com.ytpm.app.view;
+
+import io.swagger.annotations.ApiModelProperty;
+import lombok.Data;
+
+@Data
+public class YtAppListView {
+    @ApiModelProperty("应用ID")
+    private String appId;
+    @ApiModelProperty("应用名称")
+    private String appName;
+    @ApiModelProperty("包名")
+    private String packageName;
+    @ApiModelProperty("一级分类")
+    private String category;
+    @ApiModelProperty("二级分类")
+    private String subCategory;
+    @ApiModelProperty("应用启用状态")
+    private Integer enabled;
+    @ApiModelProperty("广告平台ID")
+    private String networkId;
+    @ApiModelProperty("广告平台账号ID")
+    private String nwFirmId;
+    @ApiModelProperty("广告平台账号名称")
+    private String nwFirmIdName;
+    @ApiModelProperty("二维码链接")
+    private String qrCode;
+    @ApiModelProperty("版本号")
+    private String versionCode;
+}

+ 7 - 43
yt-common/src/main/java/com/ytpm/constant/StrConstant.java

@@ -1,59 +1,23 @@
 package com.ytpm.constant;
 
 public class StrConstant {
-    public static final String PRO_STR = "pro";
     /**
      * redis 存储用户信息前缀
      */
 
-    public static final String USER_INFO_PRE = "ZL_PLATFORM_";
-    /**
-     * redis 用户登录短信 前缀
-     */
-    public static final String LOGIN_MSG_PRE = "YT_LOGIN_MSG_";
-    /**
-     * redis 修改手机号码 前缀
-     */
-    public static final String CHANGE_PHONE_NO_PRE = "YT_CHANGE_PHONE_NO_PRE_";
-    /**
-     * redis 修改登录密码 前缀
-     */
-    public static final String CHANGE_LOGIN_PWD_PRE = "YT_CHANGE_LOGIN_PWD_PRE_";
-    /**
-     * redis 期限
-     */
-    public static final String EXPIRES = "_EXPIRES";
-    /**
-     * redis 短信次数
-     */
-    public static final String TIMES = "_TIMES";
+    public static final String USER_INFO_PRE = "YT_PLATFORM_";
 
     /**
-     * redis 存储用户信息 机构ID拼接
+     * 退出登录
      */
-    public static final String USER_ORGANIZATION_ID = "_ORGANIZATION_ID_";
-    /**
-     * redis 钉钉免登陆 检验code
+    public static final int LOG_OUT = 1024;  /**
+     * 提交次数限制
      */
-    public static final String DING_TALK_FREE_CHECK_CODE = "YT_DING_TALK_LOGIN_CHECK_";
-
-    /**   redis  菜单   */
-    public static final String MENU_LIST_PRE = "YT_MENU_";
+    public static final String POST_SUBMIT_TIMES="YT_POST_SUBMIT_TIMES_";
     /**
-     * redis 业务编号
+     * 平台ID前缀
      */
-    public static final String ORDER_NO_KEY = "YT_ORDER_NO_KEY";
+    public static final String PLATFORM_ID_PREFIX="YT_";
 
-    /**   智能审批标识   */
-    public static final String AUTO_AUDIT_FLAG = "YT_AUTO_AUDIT_FLAG_";
 
-    //===================================================================
-    /**
-     * 符合
-     */
-    public static final String CONFORMITY = "符合";
-    /**
-     * 不符合
-     */
-    public static final String INCONFORMITY = "不符合";
 }

+ 1 - 0
yt-common/src/main/java/com/ytpm/general/RepMessage.java

@@ -7,6 +7,7 @@ package com.ytpm.general;
 public class RepMessage {
     public static final String QUERY_SUCCESS = "查询成功";
     public static final String MODIFY_SUCCESS = "修改成功";
+    public static final String ADD_SUCCESS = "增加成功";
     public static final String SAVE_SUCCESS = "保存成功";
     public static final String DELETE_SUCCESS = "删除成功";
     public static final String RELATIVE_SUCCESS = "关联成功";

+ 1 - 1
yt-common/src/main/java/com/ytpm/util/IDUtil.java

@@ -2,7 +2,7 @@ package com.ytpm.util;
 
 import cn.hutool.core.util.IdUtil;
 public class IDUtil {
-    private final static String PREFIX = "zlTech_";
+    private final static String PREFIX = "ytPlatform_";
 
     /**
      * 雪花算法ID 生成