From 3ae15068a2f1e8b22a6d2575f55dae6e293b1713 Mon Sep 17 00:00:00 2001 From: liyihao <1054753886@qq.com> Date: Tue, 16 Nov 2021 17:04:15 +0800 Subject: [PATCH 1/3] =?UTF-8?q?=E5=BA=94=E7=94=A8=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/controller/DataAppController.java | 158 +++++++++ .../java/com/ruoyi/data/entity/DataApp.java | 87 +++++ .../java/com/ruoyi/data/entity/DataKey.java | 73 +++++ .../com/ruoyi/data/mapper/DataAppMapper.java | 86 +++++ .../ruoyi/data/service/IDataAppService.java | 92 ++++++ .../data/service/impl/DataAppServiceImpl.java | 111 +++++++ .../resources/mapper/data/DataAppMapper.xml | 141 ++++++++ .../src/main/resources/application.yml | 15 + ruoyi-admin/src/main/resources/logback.xml | 1 + .../com/ruoyi/common/constant/Constants.java | 5 + .../core/domain/entity/data/AccessBody.java | 140 ++++++++ .../domain/entity/data/JwtAccessToken.java | 29 ++ .../ruoyi/data/filter/AccessTokenConfig.java | 46 +++ .../filter/AccessTokenFailureHandler.java | 24 ++ .../data/filter/AccessTokenProvider.java | 28 ++ .../ruoyi/data/filter/AccessTokenService.java | 196 +++++++++++ .../filter/AccessTokenSuccessHandler.java | 30 ++ .../data/filter/JwtAccessTokenFilter.java | 76 +++++ .../data/filter/RewriteAccessDenyFilter.java | 27 ++ .../framework/config/SecurityConfig.java | 29 +- ruoyi-ui/src/api/data/app.js | 65 ++++ ruoyi-ui/src/views/data/app/index.vue | 307 ++++++++++++++++++ 22 files changed, 1764 insertions(+), 2 deletions(-) create mode 100644 mobile-app/src/main/java/com/ruoyi/data/controller/DataAppController.java create mode 100644 mobile-app/src/main/java/com/ruoyi/data/entity/DataApp.java create mode 100644 mobile-app/src/main/java/com/ruoyi/data/entity/DataKey.java create mode 100644 mobile-app/src/main/java/com/ruoyi/data/mapper/DataAppMapper.java create mode 100644 mobile-app/src/main/java/com/ruoyi/data/service/IDataAppService.java create mode 100644 mobile-app/src/main/java/com/ruoyi/data/service/impl/DataAppServiceImpl.java create mode 100755 mobile-app/src/main/resources/mapper/data/DataAppMapper.xml create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/data/AccessBody.java create mode 100644 ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/data/JwtAccessToken.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenConfig.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenFailureHandler.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenProvider.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenService.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenSuccessHandler.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/data/filter/JwtAccessTokenFilter.java create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/data/filter/RewriteAccessDenyFilter.java create mode 100644 ruoyi-ui/src/api/data/app.js create mode 100644 ruoyi-ui/src/views/data/app/index.vue diff --git a/mobile-app/src/main/java/com/ruoyi/data/controller/DataAppController.java b/mobile-app/src/main/java/com/ruoyi/data/controller/DataAppController.java new file mode 100644 index 0000000..17dee17 --- /dev/null +++ b/mobile-app/src/main/java/com/ruoyi/data/controller/DataAppController.java @@ -0,0 +1,158 @@ +package com.ruoyi.data.controller; + + +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.page.TableDataInfo; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.common.utils.uuid.UUID; +import com.ruoyi.data.filter.AccessTokenService; +import com.ruoyi.common.core.domain.entity.data.AccessBody; +import com.ruoyi.data.entity.DataApp; +import com.ruoyi.data.entity.DataKey; +import com.ruoyi.data.service.IDataAppService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.util.List; + +@RestController +@RequestMapping("/data/app") +public class DataAppController extends BaseController { + + @Autowired + private IDataAppService dataAppService; + + @Autowired + private AccessTokenService accessTokenService; + + + /** + * 获取应用列表 + */ + @GetMapping("/list") + public TableDataInfo list(DataApp app) + { + + DataKey dataKey = new DataKey(); + dataKey.setUserId(getUserId()); + app.setDataKey(dataKey); + + startPage(); + List list = dataAppService.selectAppList(app); + return getDataTable(list); + } + + /** + * + * @param appId + * @param userId + * @param appKey + * @return + */ + @GetMapping("/getAccessToken") + public AjaxResult getAccessToken(@RequestParam(required = false)String appId,@RequestParam(required = false)Long userId,@RequestParam(required = false)String appKey){ + if(userId == null){ + userId = getUserId(); + } + AjaxResult ajax = new AjaxResult(); + if(appKey == null || appId == null){ + return AjaxResult.error(301,"请先申请key值"); + }else { + + //判断key值是否正确 + if(dataAppService.checkByAppKeyAndAppId(new DataKey(Long.valueOf(appId),userId,appKey)) > 0){ + String accessToken = accessTokenService.createAccessToken(new AccessBody(Long.valueOf(appId),userId,appKey)); + ajax.put("accessToken",accessToken); + }else { + return AjaxResult.error(302,"请输入正确的key值"); + } + + } + return ajax; + } + + + /** + * 用户申请key + * @param appId + */ + @GetMapping("/getKey") + public AjaxResult getKey(String appId){ + Long userId = getUserId(); + String appKey = UUID.randomUUID().toString(); + DataKey dataKey = new DataKey(Long.valueOf(appId),userId,appKey); + + return toAjax(dataAppService.insertKey(dataKey)); + +// if(row > 0){ +// return getAccessToken(appId,userId,appKey); +// }else { +// return toAjax(row); +// } + + + } + + /** + * 根据用户编号获取详细信息 + */ + @GetMapping(value = {"/{id}" }) + public AjaxResult getInfo(@PathVariable(value = "id", required = false) Long id) + { + + DataApp dataApp = dataAppService.selectById(id); + AjaxResult ajax = AjaxResult.success(); + ajax.put("dataApp",dataApp); + return ajax; + } + + /** + * 新增应用 + */ + @Log(title = "应用管理", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@Validated @RequestBody DataApp dataApp) + { + if (dataAppService.checkAppNameUnique(dataApp.getAppName()) != null) + { + return AjaxResult.error("新增应用" + dataApp.getAppName() + "'失败,应用名称已存在'"); + } + else if (dataAppService.checkUrlUnique(dataApp.getUrl()) != null) + { + return AjaxResult.error("新增应用'" + dataApp.getUrl() + "'失败,地址已存在"); + } + dataApp.setCreateBy(getUsername()); + return toAjax(dataAppService.insert(dataApp)); + } + + /** + * 修改应用 + */ + @Log(title = "应用管理", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@Validated @RequestBody DataApp dataApp) + { + + if (dataAppService.checkUrlUnique(dataApp.getUrl()) != null) + { + return AjaxResult.error("修改应用'" + dataApp.getUrl() + "'失败,地址已存在"); + } + dataApp.setUpdateBy(getUsername()); + return toAjax(dataAppService.updataApp(dataApp)); + } + + /** + * 删除应用 + */ + @Log(title = "应用管理", businessType = BusinessType.DELETE) + @DeleteMapping("/{ids}") + public AjaxResult remove(@PathVariable Long[] ids) + { + + return toAjax(dataAppService.deleteAppById(ids)); + } + +} diff --git a/mobile-app/src/main/java/com/ruoyi/data/entity/DataApp.java b/mobile-app/src/main/java/com/ruoyi/data/entity/DataApp.java new file mode 100644 index 0000000..753957f --- /dev/null +++ b/mobile-app/src/main/java/com/ruoyi/data/entity/DataApp.java @@ -0,0 +1,87 @@ +package com.ruoyi.data.entity; + + +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 数据中心 应用管理 + */ +public class DataApp extends BaseEntity { + + + private static final long serialVersionUID = 1L; + + //应用id + private Long id; + //应用名称 + private String appName; + //应用简介 + private String text; + //分类 + private String classify; + //访问接口 + private String url; + + //用户key值 + private DataKey dataKey; + + //状态吗 (是否被申请) + private int status; + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public String getAppName() { + return appName; + } + + public void setAppName(String appName) { + this.appName = appName; + } + + public String getText() { + return text; + } + + public void setText(String text) { + this.text = text; + } + + + public String getClassify() { + return classify; + } + + public void setClassify(String classify) { + this.classify = classify; + } + + public DataKey getDataKey() { + return dataKey; + } + + public void setDataKey(DataKey dataKey) { + this.dataKey = dataKey; + } + + public int getStatus() { + return status; + } + + public void setStatus(int status) { + this.status = status; + } + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } +} diff --git a/mobile-app/src/main/java/com/ruoyi/data/entity/DataKey.java b/mobile-app/src/main/java/com/ruoyi/data/entity/DataKey.java new file mode 100644 index 0000000..c3e4824 --- /dev/null +++ b/mobile-app/src/main/java/com/ruoyi/data/entity/DataKey.java @@ -0,0 +1,73 @@ +package com.ruoyi.data.entity; + +import com.ruoyi.common.core.domain.BaseEntity; + + +/** + * 用户 申请 应用的key值 + */ +public class DataKey extends BaseEntity { + + private static final long serialVersionUID = 1L; + + + private Long id; + + private Long appId; + + private Long userId; + + private String appKey; + + private String url; + + public String getUrl() { + return url; + } + + public void setUrl(String url) { + this.url = url; + } + + public DataKey() { + } + + public DataKey(Long appId, Long userId, String appKey) { + this.appId = appId; + this.userId = userId; + this.appKey = appKey; + } + + public String getAppKey() { + return appKey; + } + + public void setAppKey(String appKey) { + this.appKey = appKey; + } + + public Long getId() { + return id; + } + + public void setId(Long id) { + this.id = id; + } + + public Long getAppId() { + return appId; + } + + public void setAppId(Long appId) { + this.appId = appId; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + +} diff --git a/mobile-app/src/main/java/com/ruoyi/data/mapper/DataAppMapper.java b/mobile-app/src/main/java/com/ruoyi/data/mapper/DataAppMapper.java new file mode 100644 index 0000000..4a19fee --- /dev/null +++ b/mobile-app/src/main/java/com/ruoyi/data/mapper/DataAppMapper.java @@ -0,0 +1,86 @@ +package com.ruoyi.data.mapper; + +import com.ruoyi.data.entity.DataApp; +import com.ruoyi.data.entity.DataKey; + +import java.util.List; + +public interface DataAppMapper { + + /** + * 根据条件分页查询应用列表 + * @param app + * @return + */ + public List selectAppList(DataApp app); + + /** + * 用户申请应用key值 + * @param dataKey + * @return + */ + public int insertKey(DataKey dataKey); + + + /** + * 通过ID进行查询 + * @param id + * @return + */ + public DataApp selectById(Long id); + + + /** + * 校验用户名称是否唯一 + * + * @param appName 应用名称 + * @return 结果 + */ + public DataApp checkAppNameUnique(String appName); + + /** + * 校验手机号码是否唯一 + * + * @param url 地址 + * @return 结果 + */ + public DataApp checkUrlUnique(String url); + + /** + * 新增应用信息 + * @param dataApp + * @return + */ + public int insert(DataApp dataApp); + + + /** + * 修改信息 + * @param dataApp + * @return + */ + public int updataApp(DataApp dataApp); + + /** + * + * @param ids + * @return + */ + public int deleteAppById(Long[] ids); + + + /** + * + * @param userId + * @return + */ + public List selectAppsByUserId(Long userId); + + + /** + * 判断输入的key值是否正确 + * @param dataKey + * @return + */ + public int checkByAppKeyAndAppId(DataKey dataKey); +} diff --git a/mobile-app/src/main/java/com/ruoyi/data/service/IDataAppService.java b/mobile-app/src/main/java/com/ruoyi/data/service/IDataAppService.java new file mode 100644 index 0000000..4220cf8 --- /dev/null +++ b/mobile-app/src/main/java/com/ruoyi/data/service/IDataAppService.java @@ -0,0 +1,92 @@ +package com.ruoyi.data.service; + + +import com.ruoyi.data.entity.DataApp; +import com.ruoyi.data.entity.DataKey; + +import java.util.List; +import java.util.Map; + +/** + * + * 应用管理业务层 + * + */ +public interface IDataAppService { + + /** + * 根据条件分页查询应用列表 + * @param app + * @return + */ + public List selectAppList(DataApp app); + + /** + * 用户申请应用key值 + * @param dataKey + * @return + */ + public int insertKey(DataKey dataKey); + + + /** + * 通过ID进行查询 + * @param id + * @return + */ + public DataApp selectById(Long id); + + /** + * 校验用户名称是否唯一 + * + * @param appName 应用名称 + * @return 结果 + */ + public DataApp checkAppNameUnique(String appName); + + /** + * 校验手机号码是否唯一 + * + * @param url 地址 + * @return 结果 + */ + public DataApp checkUrlUnique(String url); + + /** + * 新增应用信息 + * @param dataApp + * @return + */ + public int insert(DataApp dataApp); + + + /** + * 修改用户信息 + * @param dataApp + * @return + */ + public int updataApp(DataApp dataApp); + + /** + * + * @param ids + * @return + */ + public int deleteAppById(Long[] ids); + + + /** + * 获取用户的 + * @param userId + * @return + */ + public Map> selectAppsByUserId(Long userId); + + /** + * 判断输入的key值是否正确 + * @param dataKey + * @return + */ + public int checkByAppKeyAndAppId(DataKey dataKey); + +} diff --git a/mobile-app/src/main/java/com/ruoyi/data/service/impl/DataAppServiceImpl.java b/mobile-app/src/main/java/com/ruoyi/data/service/impl/DataAppServiceImpl.java new file mode 100644 index 0000000..5a87674 --- /dev/null +++ b/mobile-app/src/main/java/com/ruoyi/data/service/impl/DataAppServiceImpl.java @@ -0,0 +1,111 @@ +package com.ruoyi.data.service.impl; + + +import com.ruoyi.data.entity.DataApp; +import com.ruoyi.data.entity.DataKey; +import com.ruoyi.data.mapper.DataAppMapper; +import com.ruoyi.data.service.IDataAppService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +@Service +public class DataAppServiceImpl implements IDataAppService { + + @Autowired + private DataAppMapper dataAppMapper; + + @Override + public List selectAppList(DataApp app) { + return dataAppMapper.selectAppList(app); + } + + /** + * 用户申请应用key值 + * @param dataKey + * @return + */ + @Override + public int insertKey(DataKey dataKey){ + return dataAppMapper.insertKey(dataKey); + } + + + @Override + public DataApp selectById(Long id) { + return dataAppMapper.selectById(id); + } + + /** + * 校验用户名称是否唯一 + * + * @param appName 应用名称 + * @return 结果 + */ + public DataApp checkAppNameUnique(String appName){ + return dataAppMapper.checkAppNameUnique(appName); + } + + /** + * 校验url是否唯一 + * + * @param url 地址 + * @return 结果 + */ + public DataApp checkUrlUnique(String url){ + return dataAppMapper.checkUrlUnique(url); + } + + /** + * 新增应用信息 + * @param dataApp + * @return + */ + public int insert(DataApp dataApp){ + return dataAppMapper.insert(dataApp); + } + + + /** + * 修改用户信息 + * @param dataApp + * @return + */ + public int updataApp(DataApp dataApp){ + return dataAppMapper.updataApp(dataApp); + } + + /** + * + * @param ids + * @return + */ + public int deleteAppById(Long[] ids){ + + return dataAppMapper.deleteAppById(ids); + } + + @Override + public Map> selectAppsByUserId(Long userId) { + + Map> map = new HashMap<>(); + + Listlist = dataAppMapper.selectAppsByUserId(userId); + + for( DataKey dataKey : list){ + Map map1 = new HashMap<>(); + map1.put("key",dataKey.getAppId().toString()); + map1.put("value",dataKey.getAppKey()); + map.put(dataKey.getUrl(),map1); + } + return map; + } + + @Override + public int checkByAppKeyAndAppId(DataKey dataKey) { + return dataAppMapper.checkByAppKeyAndAppId(dataKey); + } +} diff --git a/mobile-app/src/main/resources/mapper/data/DataAppMapper.xml b/mobile-app/src/main/resources/mapper/data/DataAppMapper.xml new file mode 100755 index 0000000..0cbc911 --- /dev/null +++ b/mobile-app/src/main/resources/mapper/data/DataAppMapper.xml @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select id, app_name, text, url,classify, create_by, create_time ,update_by,update_time ,remark + from data_app + + + + + + + + + + + insert into data_key ( + + app_id, + user_id, + app_key, + create_time + + ) values ( + + #{appId} , + #{userId}, + #{appKey} , + sysdate() + + ) + + + + + insert into data_app ( + + app_name, + text, + url, + create_time + )values ( + #{appName} , + #{text} , + #{text} , + sysdate() + ) + + + + + + + + + delete from data_app where id in + + #{id} + + + + + update data_app + + app_name = #{appName}, + text = #{text}, + url = #{url}, + update_time = sysdate() + + where id = #{id} + + + + + + \ No newline at end of file diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 3eaf6c9..2a8df2e 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -10,6 +10,7 @@ ruoyi: demoEnabled: true # 文件路径 示例( Windows配置D:/ruoyi/uploadPath,Linux配置 /home/ruoyi/uploadPath) profile: D:/ruoyi/uploadPath +# profile: /Users/liyihao/IdeaProjects/app-course-platform/uploadPath # 获取ip地址开关 addressEnabled: false # 验证码类型 math 数组计算 char 字符验证 @@ -38,6 +39,9 @@ logging: # Spring配置 spring: + #bean 不能注册 + main: + allow-bean-definition-overriding: true # 资源信息 messages: # 国际化资源文件路径 @@ -88,6 +92,17 @@ token: # 令牌有效期(默认30分钟) expireTime: 30 + +# accessToken配置 +accessToken: + # 令牌自定义标识 + header: AccessToken + # 令牌密钥 + secret: abcdefghijklmnopqrstuvwxyz + # 令牌有效期(默认30分钟) + expireTime: 30 + + # MyBatis配置 mybatis: # 搜索指定包别名 diff --git a/ruoyi-admin/src/main/resources/logback.xml b/ruoyi-admin/src/main/resources/logback.xml index a360583..8e8977f 100644 --- a/ruoyi-admin/src/main/resources/logback.xml +++ b/ruoyi-admin/src/main/resources/logback.xml @@ -1,6 +1,7 @@ + diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java index d36253c..95dbaed 100644 --- a/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java +++ b/ruoyi-common/src/main/java/com/ruoyi/common/constant/Constants.java @@ -69,6 +69,11 @@ public class Constants */ public static final String LOGIN_TOKEN_KEY = "login_tokens:"; + /** + * api 接口验证 redis key + */ + public static final String ACCESS_TOKEN = "access_token:"; + /** * 防重提交 redis key */ diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/data/AccessBody.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/data/AccessBody.java new file mode 100644 index 0000000..fac5c6b --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/data/AccessBody.java @@ -0,0 +1,140 @@ +package com.ruoyi.common.core.domain.entity.data; + + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Collection; + +/** + * 接口访问实体 + */ +public class AccessBody { + + private Long appId; + + private Long userId; + + private String appKey; + + private String accessToken; + + /** + * 登录时间 + */ + private Long loginTime; + + /** + * 过期时间 + */ + private Long expireTime; + + /** + * 登录IP地址 + */ + private String ipaddr; + + /** + * 登录地点 + */ + private String loginLocation; + + /** + * 浏览器类型 + */ + private String browser; + + /** + * 操作系统 + */ + private String os; + + public AccessBody( Long appId, Long userId, String appKey) { + this.appId = appId; + this.userId = userId; + this.appKey = appKey; + } + + public AccessBody() { + } + + public Long getLoginTime() { + return loginTime; + } + + public void setLoginTime(Long loginTime) { + this.loginTime = loginTime; + } + + public Long getExpireTime() { + return expireTime; + } + + public void setExpireTime(Long expireTime) { + this.expireTime = expireTime; + } + + public String getIpaddr() { + return ipaddr; + } + + public void setIpaddr(String ipaddr) { + this.ipaddr = ipaddr; + } + + public String getLoginLocation() { + return loginLocation; + } + + public void setLoginLocation(String loginLocation) { + this.loginLocation = loginLocation; + } + + public String getBrowser() { + return browser; + } + + public void setBrowser(String browser) { + this.browser = browser; + } + + public String getOs() { + return os; + } + + public void setOs(String os) { + this.os = os; + } + + public String getAccessToken() { + return accessToken; + } + + public void setAccessToken(String accessToken) { + this.accessToken = accessToken; + } + + public Long getAppId() { + return appId; + } + + public void setAppId(Long appId) { + this.appId = appId; + } + + public Long getUserId() { + return userId; + } + + public void setUserId(Long userId) { + this.userId = userId; + } + + public String getAppKey() { + return appKey; + } + + public void setAppKey(String appKey) { + this.appKey = appKey; + } +} diff --git a/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/data/JwtAccessToken.java b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/data/JwtAccessToken.java new file mode 100644 index 0000000..eaa98bb --- /dev/null +++ b/ruoyi-common/src/main/java/com/ruoyi/common/core/domain/entity/data/JwtAccessToken.java @@ -0,0 +1,29 @@ +package com.ruoyi.common.core.domain.entity.data; + +import org.springframework.security.authentication.AbstractAuthenticationToken; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Collection; + +public class JwtAccessToken extends AbstractAuthenticationToken { + + private final AccessBody accessBody; + + private final Object credentials; + + public JwtAccessToken(Collection authorities, AccessBody accessBody, Object credentials) { + super(authorities); + this.accessBody = accessBody; + this.credentials = credentials; + } + + @Override + public Object getCredentials() { + return credentials; + } + + @Override + public AccessBody getPrincipal() { + return accessBody; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenConfig.java new file mode 100644 index 0000000..32580b1 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenConfig.java @@ -0,0 +1,46 @@ +package com.ruoyi.data.filter; + + +import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.ProviderManager; +import org.springframework.security.config.annotation.web.HttpSecurityBuilder; +import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy; + +import java.util.ArrayList; +import java.util.List; + +@Configuration +public class AccessTokenConfig , B extends HttpSecurityBuilder> + extends AbstractHttpConfigurer{ + + @Override + public void configure(B builder) throws Exception { + builder.addFilterAfter(jwtAccessTokenFilter(), JwtAuthenticationTokenFilter.class); + } + + @Bean + JwtAccessTokenFilter jwtAccessTokenFilter(){ + // 使用自定义的filter + JwtAccessTokenFilter jwtAccessTokenFilter = new JwtAccessTokenFilter(); + // 新建providerManager并为filter配置provider + List provider = new ArrayList(); + AccessTokenProvider accessTokenProvider = new AccessTokenProvider(); + provider.add(accessTokenProvider); + ProviderManager providerManager = new ProviderManager(provider); + jwtAccessTokenFilter.setAuthenticationManager(providerManager); + //注入accessTokenService +// jwtAccessTokenFilter.setAccessTokenService(accessTokenService); + jwtAccessTokenFilter.setSessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy()); + jwtAccessTokenFilter.setAuthenticationSuccessHandler(new AccessTokenSuccessHandler()); + jwtAccessTokenFilter.setAuthenticationFailureHandler(new AccessTokenFailureHandler()); + + return jwtAccessTokenFilter; + } + + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenFailureHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenFailureHandler.java new file mode 100644 index 0000000..7e4c7fe --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenFailureHandler.java @@ -0,0 +1,24 @@ +package com.ruoyi.data.filter; + +import com.alibaba.fastjson.JSON; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class AccessTokenFailureHandler implements AuthenticationFailureHandler { + + + @Override + public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException { + int code = 501; + String msg = StringUtils.format("您无权访问该接口", request.getRequestURI()); + ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg))); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenProvider.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenProvider.java new file mode 100644 index 0000000..e95bc05 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenProvider.java @@ -0,0 +1,28 @@ +package com.ruoyi.data.filter; + +import com.ruoyi.common.core.domain.entity.data.AccessBody; +import com.ruoyi.common.core.domain.entity.data.JwtAccessToken; +import io.jsonwebtoken.JwtException; +import org.springframework.security.authentication.AuthenticationProvider; +import org.springframework.security.authentication.AuthenticationServiceException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; + +public class AccessTokenProvider implements AuthenticationProvider { + + + @Override + public Authentication authenticate(Authentication authentication) throws AuthenticationException { + try { + JwtAccessToken jwtAccessToken = (JwtAccessToken) authentication; + return jwtAccessToken; + }catch (JwtException e){ + throw new AuthenticationServiceException("Token invalidate"); + } + } + + @Override + public boolean supports(Class aClass) { + return aClass.isAssignableFrom(JwtAccessToken.class); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenService.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenService.java new file mode 100644 index 0000000..9c5a629 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenService.java @@ -0,0 +1,196 @@ +package com.ruoyi.data.filter; + +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.ip.AddressUtils; +import com.ruoyi.common.utils.ip.IpUtils; +import com.ruoyi.common.utils.uuid.IdUtils; +import com.ruoyi.common.core.domain.entity.data.AccessBody; +import eu.bitwalker.useragentutils.UserAgent; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletRequest; +import java.util.HashMap; +import java.util.Map; +import java.util.concurrent.TimeUnit; + + +@Component +public class AccessTokenService { + + // 令牌自定义标识 + @Value("${accessToken.header}") + private String header; + + // 令牌秘钥 + @Value("${accessToken.secret}") + private String secret; + + // 令牌有效期(默认30分钟) + @Value("${accessToken.expireTime}") + private int expireTime; + + + + protected static final long MILLIS_SECOND = 1000; + + protected static final long MILLIS_MINUTE = 60 * MILLIS_SECOND; + + private static final Long MILLIS_MINUTE_TEN = 20 * 60 * 1000L; + + @Autowired + private RedisCache redisCache; + + + /** + * 创建令牌 + * + * @param accessBody + * @return 令牌 + */ + public String createAccessToken(AccessBody accessBody) + { + String token = IdUtils.fastUUID(); + accessBody.setAccessToken(token); + setAgent(accessBody); + refreshToken(accessBody); + + Map claims = new HashMap<>(); + claims.put(Constants.ACCESS_TOKEN, token); + return createToken(claims); + } + + + /** + * 设置用户代理信息 + * + * @param accessBody + */ + public void setAgent(AccessBody accessBody) + { + UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); + String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); + accessBody.setIpaddr(ip); + accessBody.setLoginLocation(AddressUtils.getRealAddressByIP(ip)); + accessBody.setBrowser(userAgent.getBrowser().getName()); + accessBody.setOs(userAgent.getOperatingSystem().getName()); + } + + /** + * 刷新令牌有效期 + * + * @param accessBody + */ + public void refreshToken(AccessBody accessBody) + { + accessBody.setLoginTime(System.currentTimeMillis()); + accessBody.setExpireTime(accessBody.getLoginTime() + expireTime * MILLIS_MINUTE); + // 根据uuid将loginUser缓存 + String userKey = getTokenKey(accessBody.getAccessToken()); + redisCache.setCacheObject(userKey, accessBody, expireTime, TimeUnit.MINUTES); + } + + private String getTokenKey(String uuid) + { + return Constants.ACCESS_TOKEN + uuid; + } + + + /** + * 从数据声明生成令牌 + * + * @param claims 数据声明 + * @return 令牌 + */ + private String createToken(Map claims) + { + String token = Jwts.builder() + .setClaims(claims) + .signWith(SignatureAlgorithm.HS512, secret).compact(); + return token; + } + + /** + * 从令牌中获取 + * @param request + * @return + */ + public AccessBody getAccessBody(HttpServletRequest request) + { + // 获取请求携带的令牌 + String token = getToken(request); + if (StringUtils.isNotEmpty(token)) + { + try + { + Claims claims = parseToken(token); + // 解析对应的权限以及用户信息 + String uuid = (String) claims.get(Constants.ACCESS_TOKEN); + String accessToken = getTokenKey(uuid); + AccessBody accessBody = redisCache.getCacheObject(accessToken); + return accessBody; + } + catch (Exception e) + { + } + } + return null; + } + + /** + * 获取请求acces_token + * @param request + * @return + */ + private String getToken(HttpServletRequest request) + { + try{ + String token = request.getHeader(header); + if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) + { + token = token.replace(Constants.TOKEN_PREFIX, ""); + } + return token; + }catch (Exception e){ + return null; + } + + } + + /** + * 从令牌中获取数据声明 + * + * @param token 令牌 + * @return 数据声明 + */ + private Claims parseToken(String token) + { + return Jwts.parser() + .setSigningKey(secret) + .parseClaimsJws(token) + .getBody(); + } + + /** + * 验证令牌有效期,相差不足20分钟,自动刷新缓存 + * + * @param accessBody + * @return 令牌 + */ + public void verifyToken(AccessBody accessBody) + { + long expireTime = accessBody.getExpireTime(); + long currentTime = System.currentTimeMillis(); + if (expireTime - currentTime <= MILLIS_MINUTE_TEN) + { + refreshToken(accessBody); + } + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenSuccessHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenSuccessHandler.java new file mode 100644 index 0000000..d09de85 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenSuccessHandler.java @@ -0,0 +1,30 @@ +package com.ruoyi.data.filter; + +import com.alibaba.fastjson.JSON; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.authentication.AuthenticationFailureHandler; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class AccessTokenSuccessHandler implements AuthenticationSuccessHandler { + + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + if(authentication.getPrincipal() == null){ + int code = 501; + String msg = StringUtils.format("您无权访问该接口", request.getRequestURI()); + ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg))); + } + + return; + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/JwtAccessTokenFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/JwtAccessTokenFilter.java new file mode 100644 index 0000000..83bf55f --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/JwtAccessTokenFilter.java @@ -0,0 +1,76 @@ +package com.ruoyi.data.filter; + +import com.ruoyi.common.core.domain.entity.data.JwtAccessToken; +import com.ruoyi.common.core.domain.entity.data.AccessBody; +import org.springframework.security.authentication.InternalAuthenticationServiceException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter; +import org.springframework.security.web.util.matcher.RequestHeaderRequestMatcher; +import org.springframework.stereotype.Component; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + + +@Component +public class JwtAccessTokenFilter extends AbstractAuthenticationProcessingFilter { + + + //拦截请求头为AccessToken的地址 + public JwtAccessTokenFilter(){ +// super(new RequestHeaderRequestMatcher("AccessToken")); + super("/data/app/list"); + } + + +// @Override +// public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { +// HttpServletRequest request = (HttpServletRequest) req; +// HttpServletResponse response = (HttpServletResponse) res; +// +// JwtAccessToken jwtAccessToken; +// try { +// jwtAccessToken =(JwtAccessToken)attemptAuthentication(request, response); +// if (jwtAccessToken.getPrincipal() == null) { +// return; +// } +// } +// catch (InternalAuthenticationServiceException failed) { +// unsuccessfulAuthentication(request, response, failed); +// return; +// } +// catch (AuthenticationException failed) { +// // Authentication failed +// unsuccessfulAuthentication(request, response, failed); +// return; +// } +// +// successfulAuthentication(request,response,chain,jwtAccessToken); +// } + + @Override + public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException, IOException, ServletException { + + response.setCharacterEncoding("UTF-8"); + response.setHeader("Content-Type", "text/html;charset=UTF-8"); + AccessTokenService accessTokenService = new AccessTokenService(); + AccessBody accessBody = accessTokenService.getAccessBody(request); + return getAuthenticationManager().authenticate(new JwtAccessToken(null,accessBody, accessBody == null ? null:accessBody.getAccessToken())); + } + + @Override + protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { + chain.doFilter(request,response); + } + + @Override + protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { +// SecurityContextHolder.clearContext(); + } + + +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/RewriteAccessDenyFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/RewriteAccessDenyFilter.java new file mode 100644 index 0000000..735d593 --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/RewriteAccessDenyFilter.java @@ -0,0 +1,27 @@ +package com.ruoyi.data.filter; + +import com.alibaba.fastjson.JSON; +import com.ruoyi.common.constant.HttpStatus; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.utils.ServletUtils; +import com.ruoyi.common.utils.StringUtils; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; +import org.springframework.stereotype.Component; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + + +@Component +public class RewriteAccessDenyFilter implements AccessDeniedHandler { + + @Override + public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { + int code = 501; + String msg = StringUtils.format("您无权访问该接口", request.getRequestURI()); + ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg))); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java index d00f00d..ab9dec4 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -1,5 +1,8 @@ package com.ruoyi.framework.config; +import com.ruoyi.data.filter.AccessTokenConfig; +import com.ruoyi.data.filter.JwtAccessTokenFilter; +import com.ruoyi.data.filter.RewriteAccessDenyFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.http.HttpMethod; @@ -40,6 +43,20 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter @Autowired private AuthenticationEntryPointImpl unauthorizedHandler; + + /** + * access_token认证过滤器 + */ + @Autowired + private JwtAccessTokenFilter jwtAccessTokenFilter; + + /** + * 自定义无权访问拦截器返回值 + */ + @Autowired + private RewriteAccessDenyFilter rewriteAccessDenyFilter; + + /** * 退出处理类 */ @@ -98,8 +115,8 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter .sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and() // 过滤请求 .authorizeRequests() - // 对于登录login 注册register 验证码captchaImage 允许匿名访问 - .antMatchers("/login", "/register", "/captchaImage").anonymous() + // 对于登录login 注册register 验证码captchaImage 申请访问token 允许匿名访问 + .antMatchers("/login", "/register", "/captchaImage","/data/app/getAccessToken").anonymous() .antMatchers( HttpMethod.GET, "/", @@ -127,6 +144,14 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); // 添加CORS filter httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class); + + //添加自定义拦截器 +// httpSecurity.addFilterAfter(jwtAccessTokenFilter, JwtAuthenticationTokenFilter.class) +// .exceptionHandling().accessDeniedHandler(rewriteAccessDenyFilter); + httpSecurity.apply(new AccessTokenConfig<>()); + + + httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class); } diff --git a/ruoyi-ui/src/api/data/app.js b/ruoyi-ui/src/api/data/app.js new file mode 100644 index 0000000..c835002 --- /dev/null +++ b/ruoyi-ui/src/api/data/app.js @@ -0,0 +1,65 @@ +import request from '@/utils/request' +import { praseStrEmpty } from "@/utils/ruoyi"; + + +// 查询用户列表 +export function listApp(query) { + return request({ + url: '/data/app/list', + method: 'get', + params: query + }) +} + +// 申请key值 +export function applyKey(appId) { + return request({ + url: '/data/app/getKey' +"?appId="+appId , + method: 'get', + }) +} + + +// 查询应用详细 +export function getApp(id) { + return request({ + url: '/data/app/' + praseStrEmpty(id), + method: 'get' + }) +} + +// 新增应用 +export function addApp(data) { + return request({ + url: '/data/app', + method: 'post', + data: data + }) +} + +// 修改应用 +export function editApp(data) { + return request({ + url: '/data/app', + method: 'put', + data: data + }) +} + +// 删除应用 +export function delApp(id) { + return request({ + url: '/data/app/' + id, + method: 'delete' + }) +} + +// 删除应用 +export function testTest() { + return request({ + url: '/testUrl/testPrint', + method: 'get' + }) +} + + diff --git a/ruoyi-ui/src/views/data/app/index.vue b/ruoyi-ui/src/views/data/app/index.vue new file mode 100644 index 0000000..df168bd --- /dev/null +++ b/ruoyi-ui/src/views/data/app/index.vue @@ -0,0 +1,307 @@ + + + -- Gitee From a5718f05b88d5e6da6983a048223d3e1b8984a1c Mon Sep 17 00:00:00 2001 From: liyihao <1054753886@qq.com> Date: Wed, 17 Nov 2021 00:37:36 +0800 Subject: [PATCH 2/3] =?UTF-8?q?=E5=BA=94=E7=94=A8=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../com/ruoyi/chat/ab/entity/ChatFileData.java | 2 +- .../data/controller/DataAppController.java | 1 - .../com/ruoyi/data/mapper/DataAppMapper.java | 2 +- .../data/service/impl/DataAppServiceImpl.java | 2 +- .../resources/mapper/data/DataAppMapper.xml | 8 ++++---- .../ruoyi/data/filter/AccessTokenConfig.java | 17 ++++++++++++++--- .../ruoyi/data/filter/AccessTokenService.java | 8 ++++---- .../data/filter/AccessTokenSuccessHandler.java | 13 ++++++++++++- .../data/filter/JwtAccessTokenFilter.java | 18 +++++++++++++----- .../ruoyi/framework/config/SecurityConfig.java | 2 +- 10 files changed, 51 insertions(+), 22 deletions(-) diff --git a/mobile-app/src/main/java/com/ruoyi/chat/ab/entity/ChatFileData.java b/mobile-app/src/main/java/com/ruoyi/chat/ab/entity/ChatFileData.java index 185c5ab..88a2bad 100644 --- a/mobile-app/src/main/java/com/ruoyi/chat/ab/entity/ChatFileData.java +++ b/mobile-app/src/main/java/com/ruoyi/chat/ab/entity/ChatFileData.java @@ -8,7 +8,7 @@ import java.io.Serializable; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.databind.annotation.JsonSerialize; import com.fasterxml.jackson.datatype.jsr310.ser.LocalDateTimeSerializer; -import com.sun.istack.NotNull; +import com.sun.istack.internal.NotNull; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.experimental.Accessors; diff --git a/mobile-app/src/main/java/com/ruoyi/data/controller/DataAppController.java b/mobile-app/src/main/java/com/ruoyi/data/controller/DataAppController.java index 17dee17..74515e3 100644 --- a/mobile-app/src/main/java/com/ruoyi/data/controller/DataAppController.java +++ b/mobile-app/src/main/java/com/ruoyi/data/controller/DataAppController.java @@ -61,7 +61,6 @@ public class DataAppController extends BaseController { if(appKey == null || appId == null){ return AjaxResult.error(301,"请先申请key值"); }else { - //判断key值是否正确 if(dataAppService.checkByAppKeyAndAppId(new DataKey(Long.valueOf(appId),userId,appKey)) > 0){ String accessToken = accessTokenService.createAccessToken(new AccessBody(Long.valueOf(appId),userId,appKey)); diff --git a/mobile-app/src/main/java/com/ruoyi/data/mapper/DataAppMapper.java b/mobile-app/src/main/java/com/ruoyi/data/mapper/DataAppMapper.java index 4a19fee..cbd8ed7 100644 --- a/mobile-app/src/main/java/com/ruoyi/data/mapper/DataAppMapper.java +++ b/mobile-app/src/main/java/com/ruoyi/data/mapper/DataAppMapper.java @@ -82,5 +82,5 @@ public interface DataAppMapper { * @param dataKey * @return */ - public int checkByAppKeyAndAppId(DataKey dataKey); + public List checkByAppKeyAndAppId(DataKey dataKey); } diff --git a/mobile-app/src/main/java/com/ruoyi/data/service/impl/DataAppServiceImpl.java b/mobile-app/src/main/java/com/ruoyi/data/service/impl/DataAppServiceImpl.java index 5a87674..78f4f9f 100644 --- a/mobile-app/src/main/java/com/ruoyi/data/service/impl/DataAppServiceImpl.java +++ b/mobile-app/src/main/java/com/ruoyi/data/service/impl/DataAppServiceImpl.java @@ -106,6 +106,6 @@ public class DataAppServiceImpl implements IDataAppService { @Override public int checkByAppKeyAndAppId(DataKey dataKey) { - return dataAppMapper.checkByAppKeyAndAppId(dataKey); + return dataAppMapper.checkByAppKeyAndAppId(dataKey).size(); } } diff --git a/mobile-app/src/main/resources/mapper/data/DataAppMapper.xml b/mobile-app/src/main/resources/mapper/data/DataAppMapper.xml index 0cbc911..0b9586f 100755 --- a/mobile-app/src/main/resources/mapper/data/DataAppMapper.xml +++ b/mobile-app/src/main/resources/mapper/data/DataAppMapper.xml @@ -33,11 +33,11 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenConfig.java index 32580b1..3dcee67 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenConfig.java @@ -9,6 +9,7 @@ import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer; +import org.springframework.security.web.authentication.logout.LogoutFilter; import org.springframework.security.web.authentication.session.NullAuthenticatedSessionStrategy; import java.util.ArrayList; @@ -20,7 +21,7 @@ public class AccessTokenConfig , B extend @Override public void configure(B builder) throws Exception { - builder.addFilterAfter(jwtAccessTokenFilter(), JwtAuthenticationTokenFilter.class); + builder.addFilterAfter(jwtAccessTokenFilter(), LogoutFilter.class); } @Bean @@ -36,11 +37,21 @@ public class AccessTokenConfig , B extend //注入accessTokenService // jwtAccessTokenFilter.setAccessTokenService(accessTokenService); jwtAccessTokenFilter.setSessionAuthenticationStrategy(new NullAuthenticatedSessionStrategy()); - jwtAccessTokenFilter.setAuthenticationSuccessHandler(new AccessTokenSuccessHandler()); - jwtAccessTokenFilter.setAuthenticationFailureHandler(new AccessTokenFailureHandler()); + jwtAccessTokenFilter.setAuthenticationSuccessHandler(accessTokenSuccessHandler()); + jwtAccessTokenFilter.setAuthenticationFailureHandler(accessTokenFailureHandler()); return jwtAccessTokenFilter; } + @Bean + AccessTokenSuccessHandler accessTokenSuccessHandler(){ + return new AccessTokenSuccessHandler(); + } + + @Bean + AccessTokenFailureHandler accessTokenFailureHandler(){ + return new AccessTokenFailureHandler(); + } + } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenService.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenService.java index 9c5a629..5515b1f 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenService.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenService.java @@ -91,10 +91,10 @@ public class AccessTokenService { public void refreshToken(AccessBody accessBody) { accessBody.setLoginTime(System.currentTimeMillis()); - accessBody.setExpireTime(accessBody.getLoginTime() + expireTime * MILLIS_MINUTE); + accessBody.setExpireTime(accessBody.getLoginTime() + 30 * MILLIS_MINUTE); // 根据uuid将loginUser缓存 String userKey = getTokenKey(accessBody.getAccessToken()); - redisCache.setCacheObject(userKey, accessBody, expireTime, TimeUnit.MINUTES); + redisCache.setCacheObject(userKey, accessBody, 30, TimeUnit.MINUTES); } private String getTokenKey(String uuid) @@ -152,7 +152,7 @@ public class AccessTokenService { private String getToken(HttpServletRequest request) { try{ - String token = request.getHeader(header); + String token = request.getHeader("AccessToken"); if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) { token = token.replace(Constants.TOKEN_PREFIX, ""); @@ -173,7 +173,7 @@ public class AccessTokenService { private Claims parseToken(String token) { return Jwts.parser() - .setSigningKey(secret) + .setSigningKey("abcdefghijklmnopqrstuvwxyz") .parseClaimsJws(token) .getBody(); } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenSuccessHandler.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenSuccessHandler.java index d09de85..df2359f 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenSuccessHandler.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenSuccessHandler.java @@ -18,13 +18,24 @@ import java.io.IOException; public class AccessTokenSuccessHandler implements AuthenticationSuccessHandler { @Override - public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authentication) throws IOException, ServletException { if(authentication.getPrincipal() == null){ int code = 501; String msg = StringUtils.format("您无权访问该接口", request.getRequestURI()); ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg))); + }else { + chain.doFilter(request,response); } + return; + } + @Override + public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { + if(authentication.getPrincipal() == null){ + int code = 501; + String msg = StringUtils.format("您无权访问该接口", request.getRequestURI()); + ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg))); + } return; } } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/JwtAccessTokenFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/JwtAccessTokenFilter.java index 83bf55f..4ac5244 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/JwtAccessTokenFilter.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/JwtAccessTokenFilter.java @@ -2,7 +2,7 @@ package com.ruoyi.data.filter; import com.ruoyi.common.core.domain.entity.data.JwtAccessToken; import com.ruoyi.common.core.domain.entity.data.AccessBody; -import org.springframework.security.authentication.InternalAuthenticationServiceException; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; import org.springframework.security.core.context.SecurityContextHolder; @@ -19,11 +19,14 @@ import java.io.IOException; @Component public class JwtAccessTokenFilter extends AbstractAuthenticationProcessingFilter { + @Autowired + public AccessTokenSuccessHandler accessTokenSuccessHandler; + //拦截请求头为AccessToken的地址 public JwtAccessTokenFilter(){ -// super(new RequestHeaderRequestMatcher("AccessToken")); - super("/data/app/list"); + super(new RequestHeaderRequestMatcher("AccessToken")); +// super("/data/app/list"); } @@ -59,17 +62,22 @@ public class JwtAccessTokenFilter extends AbstractAuthenticationProcessingFilter response.setHeader("Content-Type", "text/html;charset=UTF-8"); AccessTokenService accessTokenService = new AccessTokenService(); AccessBody accessBody = accessTokenService.getAccessBody(request); + if(accessBody != null){ + accessTokenService.verifyToken(accessBody); + } return getAuthenticationManager().authenticate(new JwtAccessToken(null,accessBody, accessBody == null ? null:accessBody.getAccessToken())); } @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { - chain.doFilter(request,response); + AccessTokenSuccessHandler accessTokenSuccessHandler = new AccessTokenSuccessHandler(); + accessTokenSuccessHandler.onAuthenticationSuccess(request,response,chain,authResult); +// chain.doFilter(request,response); } @Override protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { -// SecurityContextHolder.clearContext(); + } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java index ab9dec4..a77e2fd 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -116,7 +116,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter // 过滤请求 .authorizeRequests() // 对于登录login 注册register 验证码captchaImage 申请访问token 允许匿名访问 - .antMatchers("/login", "/register", "/captchaImage","/data/app/getAccessToken").anonymous() + .antMatchers("/login", "/register", "/captchaImage").anonymous() .antMatchers( HttpMethod.GET, "/", -- Gitee From 4542a46177a1d02da5ee2578b8336f0b4662c0f8 Mon Sep 17 00:00:00 2001 From: liyihao <1054753886@qq.com> Date: Thu, 18 Nov 2021 10:33:03 +0800 Subject: [PATCH 3/3] =?UTF-8?q?=E5=BA=94=E7=94=A8=E7=AE=A1=E7=90=86?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/application.yml | 6 +- .../ruoyi/data/filter/AccessTokenConfig.java | 3 +- .../ruoyi/data/filter/AccessTokenService.java | 8 ++- .../com/ruoyi/data/filter/GetBeanUtil.java | 61 +++++++++++++++++++ .../data/filter/JwtAccessTokenFilter.java | 18 ++++-- .../framework/config/SecurityConfig.java | 2 + 6 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 ruoyi-framework/src/main/java/com/ruoyi/data/filter/GetBeanUtil.java diff --git a/ruoyi-admin/src/main/resources/application.yml b/ruoyi-admin/src/main/resources/application.yml index 2a8df2e..483d807 100644 --- a/ruoyi-admin/src/main/resources/application.yml +++ b/ruoyi-admin/src/main/resources/application.yml @@ -39,9 +39,9 @@ logging: # Spring配置 spring: - #bean 不能注册 - main: - allow-bean-definition-overriding: true + #bean 可以重复注册 重名覆盖 +# main: +# allow-bean-definition-overriding: true # 资源信息 messages: # 国际化资源文件路径 diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenConfig.java index 3dcee67..b8278fc 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenConfig.java @@ -1,10 +1,12 @@ package com.ruoyi.data.filter; +import com.ruoyi.common.core.redis.RedisCache; import com.ruoyi.framework.security.filter.JwtAuthenticationTokenFilter; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.core.RedisTemplate; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.authentication.ProviderManager; import org.springframework.security.config.annotation.web.HttpSecurityBuilder; @@ -53,5 +55,4 @@ public class AccessTokenConfig , B extend return new AccessTokenFailureHandler(); } - } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenService.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenService.java index 5515b1f..4481f98 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenService.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/AccessTokenService.java @@ -134,11 +134,13 @@ public class AccessTokenService { // 解析对应的权限以及用户信息 String uuid = (String) claims.get(Constants.ACCESS_TOKEN); String accessToken = getTokenKey(uuid); - AccessBody accessBody = redisCache.getCacheObject(accessToken); +// AccessBody accessBody = redisCache.getCacheObject(accessToken); + AccessBody accessBody = GetBeanUtil.getBean(RedisCache.class).getCacheObject(accessToken); return accessBody; } catch (Exception e) { + e.printStackTrace(); } } return null; @@ -152,7 +154,7 @@ public class AccessTokenService { private String getToken(HttpServletRequest request) { try{ - String token = request.getHeader("AccessToken"); + String token = request.getHeader(header); if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) { token = token.replace(Constants.TOKEN_PREFIX, ""); @@ -173,7 +175,7 @@ public class AccessTokenService { private Claims parseToken(String token) { return Jwts.parser() - .setSigningKey("abcdefghijklmnopqrstuvwxyz") + .setSigningKey(secret) .parseClaimsJws(token) .getBody(); } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/GetBeanUtil.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/GetBeanUtil.java new file mode 100644 index 0000000..291572f --- /dev/null +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/GetBeanUtil.java @@ -0,0 +1,61 @@ +package com.ruoyi.data.filter; + +import org.springframework.beans.BeansException; +import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationContextAware; +import org.springframework.stereotype.Component; + + +@Component +public class GetBeanUtil implements ApplicationContextAware { + + private static ApplicationContext applicationContext = null; + + @Override + public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { + if (GetBeanUtil.applicationContext == null) { + GetBeanUtil.applicationContext = applicationContext; + } + } + + /** + * 返回ApplicationContext + * + * @return ApplicationContext + */ + public static ApplicationContext getApplicationContext() { + return applicationContext; + } + + /** + * 返回bean + * + * @param beanName beanName + * @return bean + */ + public static Object getBean(String beanName) { + return applicationContext.getBean(beanName); + } + + /** + * 获取bean + * + * @param c c + * @param 泛型 + * @return bean + */ + public static T getBean(Class c) { + return applicationContext.getBean(c); + } + + /** + * 获取bean + * @param c c + * @param name 名称 + * @param 泛型 + * @return T 泛型 + */ + public static T getBean(String name, Class c) { + return getApplicationContext().getBean(name, c); + } +} diff --git a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/JwtAccessTokenFilter.java b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/JwtAccessTokenFilter.java index 4ac5244..e9d75ac 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/data/filter/JwtAccessTokenFilter.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/data/filter/JwtAccessTokenFilter.java @@ -2,6 +2,8 @@ package com.ruoyi.data.filter; import com.ruoyi.common.core.domain.entity.data.JwtAccessToken; import com.ruoyi.common.core.domain.entity.data.AccessBody; +import org.springframework.beans.BeanWrapper; +import org.springframework.beans.BeansException; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.Authentication; import org.springframework.security.core.AuthenticationException; @@ -15,13 +17,17 @@ import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import java.io.IOException; - -@Component public class JwtAccessTokenFilter extends AbstractAuthenticationProcessingFilter { @Autowired public AccessTokenSuccessHandler accessTokenSuccessHandler; + @Autowired + private AccessTokenFailureHandler accessTokenFailureHandler; + + @Autowired + public AccessTokenService accessTokenService; + //拦截请求头为AccessToken的地址 public JwtAccessTokenFilter(){ @@ -60,7 +66,7 @@ public class JwtAccessTokenFilter extends AbstractAuthenticationProcessingFilter response.setCharacterEncoding("UTF-8"); response.setHeader("Content-Type", "text/html;charset=UTF-8"); - AccessTokenService accessTokenService = new AccessTokenService(); + AccessTokenService accessTokenService = GetBeanUtil.getBean(AccessTokenService.class); AccessBody accessBody = accessTokenService.getAccessBody(request); if(accessBody != null){ accessTokenService.verifyToken(accessBody); @@ -70,15 +76,17 @@ public class JwtAccessTokenFilter extends AbstractAuthenticationProcessingFilter @Override protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication authResult) throws IOException, ServletException { - AccessTokenSuccessHandler accessTokenSuccessHandler = new AccessTokenSuccessHandler(); + AccessTokenSuccessHandler accessTokenSuccessHandler = GetBeanUtil.getBean(AccessTokenSuccessHandler.class); accessTokenSuccessHandler.onAuthenticationSuccess(request,response,chain,authResult); // chain.doFilter(request,response); } @Override protected void unsuccessfulAuthentication(HttpServletRequest request, HttpServletResponse response, AuthenticationException failed) throws IOException, ServletException { - + AccessTokenFailureHandler accessTokenFailureHandler = GetBeanUtil.getBean(AccessTokenFailureHandler.class); + accessTokenFailureHandler.onAuthenticationFailure(request,response,failed); } + } diff --git a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java index a77e2fd..ba9db47 100644 --- a/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java +++ b/ruoyi-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -10,6 +10,7 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity; import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.http.SessionCreationPolicy; import org.springframework.security.core.userdetails.UserDetailsService; @@ -28,6 +29,7 @@ import com.ruoyi.framework.security.handle.LogoutSuccessHandlerImpl; * @author MATAOXUN 21-10-11 开放了chat模块的接口 * @author ZHANGXILIANG 21-10-12 开放了班级列表的接口 */ +@EnableWebSecurity @EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true) public class SecurityConfig extends WebSecurityConfigurerAdapter { -- Gitee