diff --git a/README.md b/README.md index 7f775857..35e29247 100644 --- a/README.md +++ b/README.md @@ -109,8 +109,8 @@ kerwincui/wumei-smart:1.1 * [演示地址>>](https://iot.wumei.live/) ##### 项目贡献者 -|[小驿物联](https://gitee.com/iot-xiaoyi) |[guanshubiao](https://gitee.com/guanshubiao)|[crazyDull](https://gitee.com/crazyDull) |[kami0314](https://github.com/kami0314)| [sxh](https://gitee.com/sixiaohu) | [redamancy_zxp](https://gitee.com/redamancy-zxp) -|--|--|--|--|--|--| +|[小驿物联](https://gitee.com/iot-xiaoyi) |[guanshubiao](https://gitee.com/guanshubiao)|[crazyDull](https://gitee.com/crazyDull) |[kami0314](https://github.com/kami0314)| [sxh](https://gitee.com/sixiaohu) | [redamancy_zxp](https://gitee.com/redamancy-zxp) | [LEE](https://gitee.com/yueming188) +|--|--|--|--|--|--|--| ### 九、部分图片 diff --git a/app/README.md b/app/README.md index 7e45af98..80a11dac 100644 --- a/app/README.md +++ b/app/README.md @@ -1,13 +1,13 @@ #### 一、物美智能项目是开源的,可用于个人学习;商业使用请赞助该项目,获得授权;同时还提供了小程序、APP和相关教程。 #### 二、获取移动端、教程和授权的方式 -1. 赞助项目,赞助费暂定800元 -2. 参与项目,贡献代码(减免300-800元) -3. 推广项目(减免10-800元) +1. 赞助项目,赞助费暂定1500元 +2. 参与项目,贡献代码(减免300-1500元) +3. 推广项目(减免10-1500元) #### 三、参与贡献代码 -前端、后端、桌面端、移动端、嵌入式软件、嵌入式硬件、测试都可以。作者会发布一些任务到 [issues](https://gitee.com/kerwincui/wumei-smart/issues) 里面,选择没有人参与,并且自己可以完成的。Fork一份代码到自己仓库,完成后提交合并请求。作者同意后减免300-800元。参与项目开发交流群:946029159 +前端、后端、桌面端、移动端、嵌入式软件、嵌入式硬件、测试都可以。作者会发布一些任务到 [issues](https://gitee.com/kerwincui/wumei-smart/issues) 里面,选择没有人参与,并且自己可以完成的。Fork一份代码到自己仓库,完成后提交合并请求。作者同意后减免300-1500元。参与项目开发交流群:946029159 #### 四、帮助推广项目 * 原创博客,10-300元,数量不限(跟项目相关,可以是介绍、教程、diy等) @@ -17,7 +17,7 @@ * 朋友圈分享,10元/个,限制1个 * 博客分享,10元/平台,限制3个 -#### 五、通过赞助、贡献代码、推广可以加入项目内部,里面包含移动端源码和更多相关教程,并且获得一年的免费更新。目前项目还在完善,教程暂无,赞助费暂定800元。可以通过官网[http://wumei.live/](http://wumei.live/) 注册账号,联系作者加入项目内部。QQ 164770707 +#### 五、通过赞助、贡献代码、推广可以加入项目内部,里面包含移动端源码和更多相关教程,并且获得一年的免费更新。目前项目还在完善,教程暂无,赞助费暂定1500元。可以通过官网[http://wumei.live/](http://wumei.live/) 注册账号,联系作者加入项目内部。QQ 164770707

diff --git a/springboot/.gitignore b/springboot/.gitignore index f96e8c25..a9894fa7 100644 --- a/springboot/.gitignore +++ b/springboot/.gitignore @@ -24,6 +24,7 @@ target/ *.iws *.iml *.ipr +../.idea ### NetBeans ### nbproject/private/ diff --git a/springboot/pom.xml b/springboot/pom.xml index bcd64af3..b34dae8a 100644 --- a/springboot/pom.xml +++ b/springboot/pom.xml @@ -3,7 +3,7 @@ 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"> 4.0.0 - + com.wumei wumei 3.8.0 @@ -11,7 +11,7 @@ wumei http://www.wumei.live 物美智能开源生活物联网平台 - + 3.8.0 UTF-8 @@ -33,8 +33,10 @@ 4.1.2 2.3 0.9.1 + 1.16.5 + 1.5.19 - + @@ -206,6 +208,20 @@ ${wumei.version} + + + me.zhyd.oauth + JustAuth + ${justAuth.version} + + + + + com.dtflys.forest + forest-spring-boot-starter + ${forest.version} + + diff --git a/springboot/wumei-admin/src/main/resources/application-druid.yml b/springboot/wumei-admin/src/main/resources/application-druid.yml index 895458e3..6b051e3e 100644 --- a/springboot/wumei-admin/src/main/resources/application-druid.yml +++ b/springboot/wumei-admin/src/main/resources/application-druid.yml @@ -8,15 +8,20 @@ spring: master: url: jdbc:mysql://localhost/wumei-smart?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root +<<<<<<< HEAD password: root # password: 123456 +======= + password: wumei-smart + # password: 123456 +>>>>>>> 45a497af97959ef44d9172185e2ab1883a4fa25d # 从库数据源 slave: - # 从数据源开关/默认关闭 - enabled: false - url: - username: - password: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: # 初始连接数 initialSize: 5 # 最小连接池数量 @@ -27,27 +32,27 @@ spring: maxWait: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位是毫秒 timeBetweenEvictionRunsMillis: 60000 - # 配置一个连接在池中最小生存的时间,单位是毫秒 + # 配置一个连接在池中最小生存的时间,单位是毫秒 minEvictableIdleTimeMillis: 300000 - # 配置一个连接在池中最大生存的时间,单位是毫秒 + # 配置一个连接在池中最大生存的时间,单位是毫秒 maxEvictableIdleTimeMillis: 900000 - # 配置检测连接是否有效 + # 配置检测连接是否有效 validationQuery: SELECT 1 FROM DUAL testWhileIdle: true testOnBorrow: false testOnReturn: false - webStatFilter: - enabled: true + webStatFilter: + enabled: true statViewServlet: - enabled: true - # 设置白名单,不填则允许所有访问 - allow: - url-pattern: /druid/* - # 控制台管理用户名和密码 - login-username: wumei-smart - login-password: wumei-smart + enabled: true + # 设置白名单,不填则允许所有访问 + allow: + url-pattern: /druid/* + # 控制台管理用户名和密码 + login-username: wumei-smart + login-password: wumei-smart filter: - stat: + stat: enabled: true # 慢SQL记录 log-slow-sql: true @@ -55,4 +60,4 @@ spring: merge-sql: true wall: config: - multi-statement-allow: true + multi-statement-allow: true \ No newline at end of file diff --git a/springboot/wumei-admin/src/main/resources/application.yml b/springboot/wumei-admin/src/main/resources/application.yml index a98dd628..8b9e6a3a 100644 --- a/springboot/wumei-admin/src/main/resources/application.yml +++ b/springboot/wumei-admin/src/main/resources/application.yml @@ -42,15 +42,15 @@ spring: messages: # 国际化资源文件路径 basename: i18n/messages - profiles: + profiles: active: druid # 文件上传 servlet: - multipart: - # 单个文件大小 - max-file-size: 10MB - # 设置总上传的文件大小 - max-request-size: 20MB + multipart: + # 单个文件大小 + max-file-size: 10MB + # 设置总上传的文件大小 + max-request-size: 20MB # 服务模块 devtools: restart: @@ -65,8 +65,8 @@ spring: # 数据库索引 database: 0 # 密码 -# password: wumei-smart -# password: 123456 + # password: wumei-smart + # password: 123456 # 连接超时时间 timeout: 10s lettuce: @@ -79,7 +79,7 @@ spring: max-active: 8 # #连接池最大阻塞等待时间(使用负值表示没有限制) max-wait: -1ms - # mqtt 配置 + # mqtt 配置 mqtt: username: wumei-smart # 账号 password: wumei-smart # 密码 @@ -95,30 +95,30 @@ spring: core-size: 10 # 最小连接数 max-size: 30 # 最大连接数 queue-capacity: 3000 # 最大容量 - + # token配置 token: - # 令牌自定义标识 - header: Authorization - # 令牌密钥 - secret: abcdefghijklwumeismartrstuvwxyz - # 令牌有效期(默认30分钟)1440为一天 - expireTime: 1440 - + # 令牌自定义标识 + header: Authorization + # 令牌密钥 + secret: abcdefghijklwumeismartrstuvwxyz + # 令牌有效期(默认30分钟)1440为一天 + expireTime: 1440 + # MyBatis配置 mybatis: - # 搜索指定包别名 - typeAliasesPackage: com.ruoyi.**.domain - # 配置mapper的扫描,找到所有的mapper.xml映射文件 - mapperLocations: classpath*:mapper/**/*Mapper.xml - # 加载全局的配置文件 - configLocation: classpath:mybatis/mybatis-config.xml + # 搜索指定包别名 + typeAliasesPackage: com.ruoyi.**.domain + # 配置mapper的扫描,找到所有的mapper.xml映射文件 + mapperLocations: classpath*:mapper/**/*Mapper.xml + # 加载全局的配置文件 + configLocation: classpath:mybatis/mybatis-config.xml # PageHelper分页插件 -pagehelper: +pagehelper: helperDialect: mysql supportMethodsArguments: true - params: count=countSql + params: count=countSql # Swagger配置 swagger: @@ -128,10 +128,10 @@ swagger: pathMapping: /dev-api # 防止XSS攻击 -xss: +xss: # 过滤开关 enabled: true # 排除链接(多个用逗号分隔) excludes: /system/notice # 匹配链接 - urlPatterns: /system/*,/monitor/*,/tool/* + urlPatterns: /system/*,/monitor/*,/tool/* \ No newline at end of file diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java index d60afee2..cec2f9cf 100644 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java +++ b/springboot/wumei-common/src/main/java/com/ruoyi/common/constant/HttpStatus.java @@ -86,4 +86,9 @@ public class HttpStatus * 接口未实现 */ public static final int NOT_IMPLEMENTED = 501; + + /** + * 不弹窗显示 + */ + public static final int NO_MESSAGE_ALERT = 502; } diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/BindLoginBody.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/BindLoginBody.java new file mode 100644 index 00000000..bd712c47 --- /dev/null +++ b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/BindLoginBody.java @@ -0,0 +1,22 @@ +package com.ruoyi.common.core.domain.model; + +/** + * 用户登录对象 + * + * @author ruoyi + */ +public class BindLoginBody extends LoginBody +{ + /** + * 绑定id + */ + private String bindId; + + public String getBindId() { + return bindId; + } + + public void setBindId(String bindId) { + this.bindId = bindId; + } +} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/BindRegisterBody.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/BindRegisterBody.java new file mode 100644 index 00000000..c8f64a05 --- /dev/null +++ b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/domain/model/BindRegisterBody.java @@ -0,0 +1,21 @@ +package com.ruoyi.common.core.domain.model; + +/** + * 用户注册对象 + * + * @author ruoyi + */ +public class BindRegisterBody extends RegisterBody { + /** + * 绑定id + */ + private String bindId; + + public String getBindId() { + return bindId; + } + + public void setBindId(String bindId) { + this.bindId = bindId; + } +} diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java index 658926e7..551a0cd8 100644 --- a/springboot/wumei-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java +++ b/springboot/wumei-common/src/main/java/com/ruoyi/common/core/redis/RedisCache.java @@ -213,7 +213,7 @@ public class RedisCache * 删除Hash中的数据 * * @param key - * @param mapkey + * @param hkey */ public void delCacheMapValue(final String key, final String hkey) { @@ -243,4 +243,15 @@ public class RedisCache { return redisTemplate.keys(pattern); } + + /** + * 是否存在key + * + * @param key 缓存key + * @return true:存在key ;false:key不存在或者已过期 + */ + public boolean containsKey(String key) { + return redisTemplate.hasKey(key); + } + } diff --git a/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/SocialPlatformType.java b/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/SocialPlatformType.java new file mode 100644 index 00000000..4cb6be8b --- /dev/null +++ b/springboot/wumei-common/src/main/java/com/ruoyi/common/enums/SocialPlatformType.java @@ -0,0 +1,10 @@ +package com.ruoyi.common.enums; + +/** + * 第三方登录平台 + * + * @author json + */ +public enum SocialPlatformType { + Wechat, QQ +} diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java index 41006842..6980efb0 100644 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java +++ b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/config/SecurityConfig.java @@ -100,7 +100,7 @@ public class SecurityConfig extends WebSecurityConfigurerAdapter .authorizeRequests() // 对于登录login 注册register 验证码captchaImage 允许匿名访问 .antMatchers("/login", "/register", "/captchaImage","/iot/tool/register","/iot/tool/ntp","/iot/tool/download", - "/iot/tool/mqtt/auth","/iot/tool/mqtt/webhook").anonymous() + "/iot/tool/mqtt/auth","/iot/tool/mqtt/webhook","/auth/**/**").anonymous() .antMatchers( HttpMethod.GET, "/", diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java index 6131f72e..98718804 100644 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java +++ b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/SysLoginService.java @@ -6,6 +6,7 @@ import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.BadCredentialsException; import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; import org.springframework.security.core.Authentication; +import org.springframework.security.core.userdetails.UserDetails; import org.springframework.stereotype.Component; import com.ruoyi.common.constant.Constants; import com.ruoyi.common.core.domain.entity.SysUser; @@ -47,6 +48,9 @@ public class SysLoginService @Autowired private ISysConfigService configService; + @Autowired + private UserDetailsServiceImpl userDetailsServiceImpl; + /** * 登录验证 * @@ -64,6 +68,16 @@ public class SysLoginService { validateCaptcha(username, code, uuid); } + return socialLogin(username,password); + } + + /** + * 第三方验证后,调用登录方法 + * @param username 用户名 + * @param password 密码 + * @return token + */ + public String socialLogin(String username, String password){ // 用户验证 Authentication authentication = null; try @@ -92,6 +106,25 @@ public class SysLoginService return tokenService.createToken(loginUser); } + /** + * 跳转登录认证接口 + * @param username + * @param encodePwd + * @return + */ + public String redirectLogin(String username,String encodePwd){ + UserDetails userDetails=userDetailsServiceImpl.loadUserByUsername(username); + if(!userDetails.getPassword().equals(encodePwd)){ + throw new UserPasswordNotMatchException(); + } + AsyncManager.me().execute(AsyncFactory.recordLogininfor(username, Constants.LOGIN_SUCCESS, MessageUtils.message("user.login.success"))); + LoginUser loginUser = (LoginUser) userDetails; + recordLoginInfo(loginUser.getUserId()); + // 生成token + return tokenService.createToken(loginUser); + + } + /** * 校验验证码 * diff --git a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java index bf28e0f5..308171b5 100644 --- a/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java +++ b/springboot/wumei-framework/src/main/java/com/ruoyi/framework/web/service/TokenService.java @@ -4,6 +4,7 @@ import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; import javax.servlet.http.HttpServletRequest; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @@ -26,8 +27,7 @@ import io.jsonwebtoken.SignatureAlgorithm; * @author ruoyi */ @Component -public class TokenService -{ +public class TokenService { // 令牌自定义标识 @Value("${token.header}") private String header; @@ -54,23 +54,27 @@ public class TokenService * * @return 用户信息 */ - public LoginUser getLoginUser(HttpServletRequest request) - { + public LoginUser getLoginUser(HttpServletRequest request) { // 获取请求携带的令牌 String token = getToken(request); - if (StringUtils.isNotEmpty(token)) - { - try - { + return getLoginUserByToken(token); + } + + /** + * 获取用户身份信息 + * + * @return 用户信息 + */ + public LoginUser getLoginUserByToken(String token) { + if (StringUtils.isNotEmpty(token)) { + try { Claims claims = parseToken(token); // 解析对应的权限以及用户信息 String uuid = (String) claims.get(Constants.LOGIN_USER_KEY); String userKey = getTokenKey(uuid); LoginUser user = redisCache.getCacheObject(userKey); return user; - } - catch (Exception e) - { + } catch (Exception e) { } } return null; @@ -79,10 +83,8 @@ public class TokenService /** * 设置用户身份信息 */ - public void setLoginUser(LoginUser loginUser) - { - if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) - { + public void setLoginUser(LoginUser loginUser) { + if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) { refreshToken(loginUser); } } @@ -90,10 +92,8 @@ public class TokenService /** * 删除用户身份信息 */ - public void delLoginUser(String token) - { - if (StringUtils.isNotEmpty(token)) - { + public void delLoginUser(String token) { + if (StringUtils.isNotEmpty(token)) { String userKey = getTokenKey(token); redisCache.deleteObject(userKey); } @@ -105,8 +105,7 @@ public class TokenService * @param loginUser 用户信息 * @return 令牌 */ - public String createToken(LoginUser loginUser) - { + public String createToken(LoginUser loginUser) { String token = IdUtils.fastUUID(); loginUser.setToken(token); setUserAgent(loginUser); @@ -123,12 +122,10 @@ public class TokenService * @param loginUser * @return 令牌 */ - public void verifyToken(LoginUser loginUser) - { + public void verifyToken(LoginUser loginUser) { long expireTime = loginUser.getExpireTime(); long currentTime = System.currentTimeMillis(); - if (expireTime - currentTime <= MILLIS_MINUTE_TEN) - { + if (expireTime - currentTime <= MILLIS_MINUTE_TEN) { refreshToken(loginUser); } } @@ -138,8 +135,7 @@ public class TokenService * * @param loginUser 登录信息 */ - public void refreshToken(LoginUser loginUser) - { + public void refreshToken(LoginUser loginUser) { loginUser.setLoginTime(System.currentTimeMillis()); loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE); // 根据uuid将loginUser缓存 @@ -152,8 +148,7 @@ public class TokenService * * @param loginUser 登录信息 */ - public void setUserAgent(LoginUser loginUser) - { + public void setUserAgent(LoginUser loginUser) { UserAgent userAgent = UserAgent.parseUserAgentString(ServletUtils.getRequest().getHeader("User-Agent")); String ip = IpUtils.getIpAddr(ServletUtils.getRequest()); loginUser.setIpaddr(ip); @@ -168,8 +163,7 @@ public class TokenService * @param claims 数据声明 * @return 令牌 */ - private String createToken(Map claims) - { + private String createToken(Map claims) { String token = Jwts.builder() .setClaims(claims) .signWith(SignatureAlgorithm.HS512, secret).compact(); @@ -182,8 +176,7 @@ public class TokenService * @param token 令牌 * @return 数据声明 */ - private Claims parseToken(String token) - { + private Claims parseToken(String token) { return Jwts.parser() .setSigningKey(secret) .parseClaimsJws(token) @@ -196,8 +189,7 @@ public class TokenService * @param token 令牌 * @return 用户名 */ - public String getUsernameFromToken(String token) - { + public String getUsernameFromToken(String token) { Claims claims = parseToken(token); return claims.getSubject(); } @@ -208,18 +200,15 @@ public class TokenService * @param request * @return token */ - private String getToken(HttpServletRequest request) - { + private String getToken(HttpServletRequest request) { String token = request.getHeader(header); - if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) - { + if (StringUtils.isNotEmpty(token) && token.startsWith(Constants.TOKEN_PREFIX)) { token = token.replace(Constants.TOKEN_PREFIX, ""); } return token; } - private String getTokenKey(String uuid) - { + private String getTokenKey(String uuid) { return Constants.LOGIN_TOKEN_KEY + uuid; } } diff --git a/springboot/wumei-iot/pom.xml b/springboot/wumei-iot/pom.xml index 3c67c32b..75f692dc 100644 --- a/springboot/wumei-iot/pom.xml +++ b/springboot/wumei-iot/pom.xml @@ -74,6 +74,19 @@ 3.8.0 + + + me.zhyd.oauth + JustAuth + + + + + + com.dtflys.forest + forest-spring-boot-starter + + diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SocialLoginController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SocialLoginController.java new file mode 100644 index 00000000..32d5a5c8 --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SocialLoginController.java @@ -0,0 +1,103 @@ +package com.ruoyi.iot.controller; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.BindLoginBody; +import com.ruoyi.common.core.domain.model.BindRegisterBody; +import com.ruoyi.iot.service.ISocialLoginService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiImplicitParam; +import io.swagger.annotations.ApiOperation; +import me.zhyd.oauth.model.AuthCallback; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.*; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 第三方登录接口Controller + * + * @author json + * @date 2022-04-12 + */ +@Api(tags = "第三方登录接口") +@RestController +@RequestMapping("/auth") +public class SocialLoginController { + + @Autowired + private ISocialLoginService iSocialLoginService; + + + @GetMapping("/render/{source}") + @ApiOperation("跳转api") + @ApiImplicitParam(name = "source", value = "登录类型", required = true, dataType = "String", paramType = "path", dataTypeClass = String.class) + public void renderAuth(HttpServletResponse httpServletResponse, HttpServletRequest httpServletRequest, @PathVariable String source) throws IOException { + // 生成授权页面 + httpServletResponse.sendRedirect(iSocialLoginService.renderAuth(source, httpServletRequest)); + } + + @GetMapping("/callback/{source}") + @ApiOperation("回调api") + @ApiImplicitParam(name = "source", value = "平台来源", required = true, dataType = "String", paramType = "path", dataTypeClass = String.class) + public void login(@PathVariable("source") String source, AuthCallback authCallback, HttpServletResponse httpServletResponse, HttpServletRequest httpServletRequest) throws IOException { + //回调接口 + httpServletResponse.sendRedirect(iSocialLoginService.callback(source, authCallback, httpServletRequest)); + } + + @GetMapping("/checkBindId/{bindId}") + @ApiOperation("检查bindId") + @ApiImplicitParam(name = "bindId", value = "绑定ID", required = true, dataType = "String", paramType = "path", dataTypeClass = String.class) + public AjaxResult checkBindId(HttpServletResponse httpServletResponse, @PathVariable String bindId) { + return iSocialLoginService.checkBindId(bindId); + } + + @GetMapping("/getErrorMsg/{errorId}") + @ApiOperation("获取errorMsg") + @ApiImplicitParam(name = "errorId", value = "错误提示ID", required = true, dataType = "String", paramType = "path", dataTypeClass = String.class) + public AjaxResult getErrorMsg(HttpServletResponse httpServletResponse, @PathVariable String errorId) { + return iSocialLoginService.getErrorMsg(errorId); + } + + /** + * 已经绑定账户,跳转登录接口 + * + * @param loginId + * @return + */ + @GetMapping("/login/{loginId}") + @ApiOperation("跳转登录api") + @ApiImplicitParam(name = "loginId", value = "登录Id", required = true, dataType = "String", paramType = "path", dataTypeClass = String.class) + public AjaxResult socialLogin(@PathVariable String loginId) { + // 生成授权页面 + return iSocialLoginService.socialLogin(loginId); + } + + /** + * 登录方法 + * + * @param bindLoginBody 绑定登录信息 + * @return 结果 + */ + @PostMapping("/bind/login") + public AjaxResult bindLogin(@RequestBody BindLoginBody bindLoginBody) { + return iSocialLoginService.bindLogin(bindLoginBody); + } + + /** + * 注册绑定接口 + * + * @param bindRegisterBody 注册信息 + * @return + */ + @PostMapping("/bind/register") + public AjaxResult bindRegister(@RequestBody BindRegisterBody bindRegisterBody) { + return iSocialLoginService.bindRegister(bindRegisterBody); + } + + +} + + + diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SocialPlatformController.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SocialPlatformController.java new file mode 100644 index 00000000..4a6e3ffb --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/controller/SocialPlatformController.java @@ -0,0 +1,104 @@ +package com.ruoyi.iot.controller; + +import java.util.List; +import javax.servlet.http.HttpServletResponse; + +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PostMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.DeleteMapping; +import org.springframework.web.bind.annotation.PathVariable; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; +import com.ruoyi.common.annotation.Log; +import com.ruoyi.common.core.controller.BaseController; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.enums.BusinessType; +import com.ruoyi.iot.domain.SocialPlatform; +import com.ruoyi.iot.service.ISocialPlatformService; +import com.ruoyi.common.utils.poi.ExcelUtil; +import com.ruoyi.common.core.page.TableDataInfo; + +/** + * 第三方登录平台控制Controller + * + * @author kerwincui + * @date 2022-04-11 + */ +@Api(tags = "第三方登录平台") +@RestController +@RequestMapping("/iot/platform") +public class SocialPlatformController extends BaseController { + @Autowired + private ISocialPlatformService socialPlatformService; + + /** + * 查询第三方登录平台控制列表 + */ + @PreAuthorize("@ss.hasPermi('iot:platform:list')") + @GetMapping("/list") + @ApiOperation("第三方登录平台分页列表") + public TableDataInfo list(SocialPlatform socialPlatform) { + startPage(); + List list = socialPlatformService.selectSocialPlatformList(socialPlatform); + return getDataTable(list); + } + + /** + * 导出第三方登录平台控制列表 + */ + @PreAuthorize("@ss.hasPermi('iot:platform:export')") + @Log(title = "第三方登录平台控制", businessType = BusinessType.EXPORT) + @PostMapping("/export") + public void export(HttpServletResponse response, SocialPlatform socialPlatform) { + List list = socialPlatformService.selectSocialPlatformList(socialPlatform); + ExcelUtil util = new ExcelUtil(SocialPlatform.class); + util.exportExcel(response, list, "第三方登录平台控制数据"); + } + + /** + * 获取第三方登录平台控制详细信息 + */ + @PreAuthorize("@ss.hasPermi('iot:platform:query')") + @GetMapping(value = "/{socialPlatformId}") + public AjaxResult getInfo(@PathVariable("socialPlatformId") Long socialPlatformId) { + return AjaxResult.success(socialPlatformService.selectSocialPlatformBySocialPlatformId(socialPlatformId)); + } + + /** + * 新增第三方登录平台控制 + */ + @PreAuthorize("@ss.hasPermi('iot:platform:add')") + @Log(title = "第三方登录平台控制", businessType = BusinessType.INSERT) + @PostMapping + public AjaxResult add(@RequestBody SocialPlatform socialPlatform) { + socialPlatform.setCreateBy(getUsername()); + return toAjax(socialPlatformService.insertSocialPlatform(socialPlatform)); + } + + /** + * 修改第三方登录平台控制 + */ + @PreAuthorize("@ss.hasPermi('iot:platform:edit')") + @Log(title = "第三方登录平台控制", businessType = BusinessType.UPDATE) + @PutMapping + public AjaxResult edit(@RequestBody SocialPlatform socialPlatform) { + socialPlatform.setUpdateBy(getUsername()); + return toAjax(socialPlatformService.updateSocialPlatform(socialPlatform)); + } + + /** + * 删除第三方登录平台控制 + */ + @PreAuthorize("@ss.hasPermi('iot:platform:remove')") + @Log(title = "第三方登录平台控制", businessType = BusinessType.DELETE) + @DeleteMapping("/{socialPlatformIds}") + public AjaxResult remove(@PathVariable Long[] socialPlatformIds) { + return toAjax(socialPlatformService.deleteSocialPlatformBySocialPlatformIds(socialPlatformIds)); + } +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/SocialPlatform.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/SocialPlatform.java new file mode 100644 index 00000000..5bb9f0b5 --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/SocialPlatform.java @@ -0,0 +1,176 @@ +package com.ruoyi.iot.domain; + +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; + +/** + * 第三方登录平台控制对象 iot_social_platform + * + * @author kerwincui + * @date 2022-04-11 + */ +public class SocialPlatform extends BaseEntity { + private static final long serialVersionUID = 1L; + + /** + * 第三方登录平台主键 + */ + private Long socialPlatformId; + + /** + * 第三方登录平台 + */ + @Excel(name = "第三方登录平台") + private String platform; + + /** + * 0、内部上线 1、上线 2、下线 + */ + @Excel(name = "0、内部上线 1、上线 2、下线") + private String status; + + /** + * 第三方平台申请Id + */ + @Excel(name = "第三方平台申请Id") + private String clientId; + + /** + * 第三方平台密钥 + */ + @Excel(name = "第三方平台密钥") + private String secretKey; + + /** + * 用户认证后跳转地址 + */ + @Excel(name = "用户认证后跳转地址") + private String redirectUri; + + /** + * 删除标记位(0代表存在,2代表删除) + */ + private String delFlag; + + /** + * 绑定注册登录uri + */ + @Excel(name = "绑定注册登录uri") + private String bindUri; + + /** + * 跳转登录uri + */ + @Excel(name = "跳转登录uri") + private String redirectLoginUri; + + /** + * 错误提示uri + */ + @Excel(name = "错误提示uri") + private String errorMsgUri; + + public Long getSocialPlatformId() { + return socialPlatformId; + } + + public void setSocialPlatformId(Long socialPlatformId) { + this.socialPlatformId = socialPlatformId; + } + + public String getPlatform() { + return platform; + } + + public void setPlatform(String platform) { + this.platform = platform; + } + + public String getStatus() { + return status; + } + + public void setStatus(String status) { + this.status = status; + } + + public String getClientId() { + return clientId; + } + + public void setClientId(String clientId) { + this.clientId = clientId; + } + + public String getSecretKey() { + return secretKey; + } + + public void setSecretKey(String secretKey) { + this.secretKey = secretKey; + } + + public String getRedirectUri() { + return redirectUri; + } + + public void setRedirectUri(String redirectUri) { + this.redirectUri = redirectUri; + } + + public String getDelFlag() { + return delFlag; + } + + public void setDelFlag(String delFlag) { + this.delFlag = delFlag; + } + + public String getBindUri() { + return bindUri; + } + + public void setBindUri(String bindUri) { + this.bindUri = bindUri; + } + + public String getRedirectLoginUri() { + return redirectLoginUri; + } + + public void setRedirectLoginUri(String redirectLoginUri) { + this.redirectLoginUri = redirectLoginUri; + } + + public String getErrorMsgUri() { + return errorMsgUri; + } + + public void setErrorMsgUri(String errorMsgUri) { + this.errorMsgUri = errorMsgUri; + } + + @Override + public String toString() { + return new ToStringBuilder(this, ToStringStyle.MULTI_LINE_STYLE) + .append("socialPlatformId", getSocialPlatformId()) + .append("platform", getPlatform()) + .append("status", getStatus()) + .append("clientId", getClientId()) + .append("secretKey", getSecretKey()) + .append("redirectUri", getRedirectUri()) + .append("delFlag", getDelFlag()) + .append("createBy", getCreateBy()) + .append("createTime", getCreateTime()) + .append("updateTime", getUpdateTime()) + .append("updateBy", getUpdateBy()) + .append("remark", getRemark()) + .append("bindUri", getBindUri()) + .append("redirectLoginUri", getRedirectLoginUri()) + .append("errorMsgUri", getErrorMsgUri()) + .toString(); + } + +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/SocialUser.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/SocialUser.java new file mode 100644 index 00000000..f0680e9e --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/domain/SocialUser.java @@ -0,0 +1,376 @@ +package com.ruoyi.iot.domain; + +import org.apache.commons.lang3.builder.ToStringBuilder; +import org.apache.commons.lang3.builder.ToStringStyle; +import com.ruoyi.common.annotation.Excel; +import com.ruoyi.common.core.domain.BaseEntity; + +/** + * 用户第三方用户信息对象 iot_social_user + * + * @author json + * @date 2022-04-18 + */ +public class SocialUser extends BaseEntity +{ + private static final long serialVersionUID = 1L; + + /** 第三方系统用户表主键 */ + private Long socialUserId; + + /** 第三方系统的唯一ID */ + @Excel(name = "第三方系统的唯一ID") + private String uuid; + + /** 第三方用户来源 */ + @Excel(name = "第三方用户来源") + private String source; + + /** 用户的授权令牌 */ + @Excel(name = "用户的授权令牌") + private String accessToken; + + /** 第三方用户的授权令牌的有效期(部分平台可能没有) */ + @Excel(name = "第三方用户的授权令牌的有效期", readConverterExp = "部=分平台可能没有") + private Long expireIn; + + /** 刷新令牌(部分平台可能没有) */ + @Excel(name = "刷新令牌(部分平台可能没有)") + private String refreshToken; + + /** 第三方用户的 open id(部分平台可能没有) */ + @Excel(name = "第三方用户的 open id", readConverterExp = "部=分平台可能没有") + private String openId; + + /** 第三方用户的 ID(部分平台可能没有) */ + @Excel(name = "第三方用户的 ID(部分平台可能没有)") + private String uid; + + /** 个别平台的授权信息(部分平台可能没有) */ + @Excel(name = "个别平台的授权信息", readConverterExp = "部=分平台可能没有") + private String accessCode; + + /** 第三方用户的 union id(部分平台可能没有) */ + @Excel(name = "第三方用户的 union id(部分平台可能没有)") + private String unionId; + + /** 第三方用户授予的权限(部分平台可能没有) */ + @Excel(name = "第三方用户授予的权限(部分平台可能没有)") + private String scope; + + /** 个别平台的授权信息(部分平台可能没有) */ + @Excel(name = "个别平台的授权信息", readConverterExp = "部=分平台可能没有") + private String tokenType; + + /** id token(部分平台可能没有) */ + @Excel(name = "id token", readConverterExp = "部=分平台可能没有") + private String idToken; + + /** 小米平台用户的附带属性(部分平台可能没有) */ + @Excel(name = "小米平台用户的附带属性", readConverterExp = "部=分平台可能没有") + private String macAlgorithm; + + /** 小米平台用户的附带属性(部分平台可能没有) */ + @Excel(name = "小米平台用户的附带属性(部分平台可能没有)") + private String macKey; + + /** 用户的授权code(部分平台可能没有) */ + @Excel(name = "用户的授权code", readConverterExp = "部=分平台可能没有") + private String code; + + /** Twitter平台用户的附带属性(部分平台可能没有) */ + @Excel(name = "Twitter平台用户的附带属性(部分平台可能没有)") + private String oauthToken; + + /** Twitter平台用户的附带属性(部分平台可能没有) */ + @Excel(name = "Twitter平台用户的附带属性(部分平台可能没有)") + private String oauthTokenSecret; + + /** 删除标记位(0代表存在,2代表删除) */ + private String delFlag; + + /** 绑定状态(0:未绑定,1:绑定) */ + @Excel(name = "绑定状态(0:未绑定,1:绑定)") + private String status; + + /** 用户ID */ + @Excel(name = "用户ID") + private Long sysUserId; + + /** 用户名 */ + @Excel(name = "用户名") + private String username; + + /** 用户昵称 */ + @Excel(name = "用户昵称") + private String nickname; + + /** 用户头像 */ + @Excel(name = "用户头像") + private String avatar; + + /** 用户性别 */ + @Excel(name = "用户性别") + private Integer gender; + + public void setSocialUserId(Long socialUserId) + { + this.socialUserId = socialUserId; + } + + public Long getSocialUserId() + { + return socialUserId; + } + public void setUuid(String uuid) + { + this.uuid = uuid; + } + + public String getUuid() + { + return uuid; + } + public void setSource(String source) + { + this.source = source; + } + + public String getSource() + { + return source; + } + public void setAccessToken(String accessToken) + { + this.accessToken = accessToken; + } + + public String getAccessToken() + { + return accessToken; + } + public void setExpireIn(Long expireIn) + { + this.expireIn = expireIn; + } + + public Long getExpireIn() + { + return expireIn; + } + public void setRefreshToken(String refreshToken) + { + this.refreshToken = refreshToken; + } + + public String getRefreshToken() + { + return refreshToken; + } + public void setOpenId(String openId) + { + this.openId = openId; + } + + public String getOpenId() + { + return openId; + } + public void setUid(String uid) + { + this.uid = uid; + } + + public String getUid() + { + return uid; + } + public void setAccessCode(String accessCode) + { + this.accessCode = accessCode; + } + + public String getAccessCode() + { + return accessCode; + } + public void setUnionId(String unionId) + { + this.unionId = unionId; + } + + public String getUnionId() + { + return unionId; + } + public void setScope(String scope) + { + this.scope = scope; + } + + public String getScope() + { + return scope; + } + public void setTokenType(String tokenType) + { + this.tokenType = tokenType; + } + + public String getTokenType() + { + return tokenType; + } + public void setIdToken(String idToken) + { + this.idToken = idToken; + } + + public String getIdToken() + { + return idToken; + } + public void setMacAlgorithm(String macAlgorithm) + { + this.macAlgorithm = macAlgorithm; + } + + public String getMacAlgorithm() + { + return macAlgorithm; + } + public void setMacKey(String macKey) + { + this.macKey = macKey; + } + + public String getMacKey() + { + return macKey; + } + public void setCode(String code) + { + this.code = code; + } + + public String getCode() + { + return code; + } + public void setOauthToken(String oauthToken) + { + this.oauthToken = oauthToken; + } + + public String getOauthToken() + { + return oauthToken; + } + public void setOauthTokenSecret(String oauthTokenSecret) + { + this.oauthTokenSecret = oauthTokenSecret; + } + + public String getOauthTokenSecret() + { + return oauthTokenSecret; + } + public void setDelFlag(String delFlag) + { + this.delFlag = delFlag; + } + + public String getDelFlag() + { + return delFlag; + } + public void setStatus(String status) + { + this.status = status; + } + + public String getStatus() + { + return status; + } + public void setSysUserId(Long sysUserId) + { + this.sysUserId = sysUserId; + } + + public Long getSysUserId() + { + return sysUserId; + } + public void setUsername(String username) + { + this.username = username; + } + + public String getUsername() + { + return username; + } + public void setNickname(String nickname) + { + this.nickname = nickname; + } + + public String getNickname() + { + return nickname; + } + public void setAvatar(String avatar) + { + this.avatar = avatar; + } + + public String getAvatar() + { + return avatar; + } + public void setGender(Integer gender) + { + this.gender = gender; + } + + public Integer getGender() + { + return gender; + } + + @Override + public String toString() { + return new ToStringBuilder(this,ToStringStyle.MULTI_LINE_STYLE) + .append("socialUserId", getSocialUserId()) + .append("uuid", getUuid()) + .append("source", getSource()) + .append("accessToken", getAccessToken()) + .append("expireIn", getExpireIn()) + .append("refreshToken", getRefreshToken()) + .append("openId", getOpenId()) + .append("uid", getUid()) + .append("accessCode", getAccessCode()) + .append("unionId", getUnionId()) + .append("scope", getScope()) + .append("tokenType", getTokenType()) + .append("idToken", getIdToken()) + .append("macAlgorithm", getMacAlgorithm()) + .append("macKey", getMacKey()) + .append("code", getCode()) + .append("oauthToken", getOauthToken()) + .append("oauthTokenSecret", getOauthTokenSecret()) + .append("createTime", getCreateTime()) + .append("createBy", getCreateBy()) + .append("updateTime", getUpdateTime()) + .append("updateBy", getUpdateBy()) + .append("delFlag", getDelFlag()) + .append("status", getStatus()) + .append("sysUserId", getSysUserId()) + .append("username", getUsername()) + .append("nickname", getNickname()) + .append("avatar", getAvatar()) + .append("gender", getGender()) + .toString(); + } +} \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SocialPlatformMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SocialPlatformMapper.java new file mode 100644 index 00000000..eb0049cc --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SocialPlatformMapper.java @@ -0,0 +1,69 @@ +package com.ruoyi.iot.mapper; + +import java.util.List; +import com.ruoyi.iot.domain.SocialPlatform; + +/** + * 第三方登录平台控制Mapper接口 + * + * @author kerwincui + * @date 2022-04-11 + */ +public interface SocialPlatformMapper +{ + /** + * 查询第三方登录平台控制 + * + * @param socialPlatformId 第三方登录平台控制主键 + * @return 第三方登录平台控制 + */ + public SocialPlatform selectSocialPlatformBySocialPlatformId(Long socialPlatformId); + + /** + * 查询第三方登录平台控制 + * + * @param platform 第三方登录平台名称 + * @return 第三方登录平台控制 + */ + public SocialPlatform selectSocialPlatformByPlatform(String platform); + + /** + * 查询第三方登录平台控制列表 + * + * @param socialPlatform 第三方登录平台控制 + * @return 第三方登录平台控制集合 + */ + public List selectSocialPlatformList(SocialPlatform socialPlatform); + + /** + * 新增第三方登录平台控制 + * + * @param socialPlatform 第三方登录平台控制 + * @return 结果 + */ + public int insertSocialPlatform(SocialPlatform socialPlatform); + + /** + * 修改第三方登录平台控制 + * + * @param socialPlatform 第三方登录平台控制 + * @return 结果 + */ + public int updateSocialPlatform(SocialPlatform socialPlatform); + + /** + * 删除第三方登录平台控制 + * + * @param socialPlatformId 第三方登录平台控制主键 + * @return 结果 + */ + public int deleteSocialPlatformBySocialPlatformId(Long socialPlatformId); + + /** + * 批量删除第三方登录平台控制 + * + * @param socialPlatformIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSocialPlatformBySocialPlatformIds(Long[] socialPlatformIds); +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SocialUserMapper.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SocialUserMapper.java new file mode 100644 index 00000000..56d3b8e6 --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/mapper/SocialUserMapper.java @@ -0,0 +1,61 @@ +package com.ruoyi.iot.mapper; + +import java.util.List; +import com.ruoyi.iot.domain.SocialUser; + +/** + * 用户第三方用户信息Mapper接口 + * + * @author json + * @date 2022-04-18 + */ +public interface SocialUserMapper +{ + /** + * 查询用户第三方用户信息 + * + * @param socialUserId 用户第三方用户信息主键 + * @return 用户第三方用户信息 + */ + public SocialUser selectSocialUserBySocialUserId(Long socialUserId); + + /** + * 查询用户第三方用户信息列表 + * + * @param socialUser 用户第三方用户信息 + * @return 用户第三方用户信息集合 + */ + public List selectSocialUserList(SocialUser socialUser); + + /** + * 新增用户第三方用户信息 + * + * @param socialUser 用户第三方用户信息 + * @return 结果 + */ + public int insertSocialUser(SocialUser socialUser); + + /** + * 修改用户第三方用户信息 + * + * @param socialUser 用户第三方用户信息 + * @return 结果 + */ + public int updateSocialUser(SocialUser socialUser); + + /** + * 删除用户第三方用户信息 + * + * @param socialUserId 用户第三方用户信息主键 + * @return 结果 + */ + public int deleteSocialUserBySocialUserId(Long socialUserId); + + /** + * 批量删除用户第三方用户信息 + * + * @param socialUserIds 需要删除的数据主键集合 + * @return 结果 + */ + public int deleteSocialUserBySocialUserIds(Long[] socialUserIds); +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/AuthRequestWrap.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/AuthRequestWrap.java new file mode 100644 index 00000000..f37b7b38 --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/AuthRequestWrap.java @@ -0,0 +1,26 @@ +package com.ruoyi.iot.model.login; + +import com.ruoyi.iot.domain.SocialPlatform; +import me.zhyd.oauth.request.AuthRequest; + +public class AuthRequestWrap { + private AuthRequest authRequest; + + private SocialPlatform socialPlatform; + + public AuthRequest getAuthRequest() { + return authRequest; + } + + public void setAuthRequest(AuthRequest authRequest) { + this.authRequest = authRequest; + } + + public SocialPlatform getSocialPlatform() { + return socialPlatform; + } + + public void setSocialPlatform(SocialPlatform socialPlatform) { + this.socialPlatform = socialPlatform; + } +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/BindIdValue.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/BindIdValue.java new file mode 100644 index 00000000..b3e3e9c6 --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/BindIdValue.java @@ -0,0 +1,23 @@ +package com.ruoyi.iot.model.login; + +public class BindIdValue { + + private String uuid; + private String source; + + public String getSource() { + return source; + } + + public void setSource(String source) { + this.source = source; + } + + public String getUuid() { + return uuid; + } + + public void setUuid(String uuid) { + this.uuid = uuid; + } +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/LoginIdValue.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/LoginIdValue.java new file mode 100644 index 00000000..b348ed58 --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/model/login/LoginIdValue.java @@ -0,0 +1,22 @@ +package com.ruoyi.iot.model.login; + +public class LoginIdValue { + String username; + String password; + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public String getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IAuthRequestFactory.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IAuthRequestFactory.java new file mode 100644 index 00000000..3515ba4e --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/IAuthRequestFactory.java @@ -0,0 +1,15 @@ +package com.ruoyi.iot.service; + +import com.ruoyi.iot.model.login.AuthRequestWrap; + +/** + * AuthRequest简单工程类接口 + * + * @author json + * @date 2022-04-12 + */ +public interface IAuthRequestFactory { + + AuthRequestWrap getAuthRequest(String source); + +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialLoginService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialLoginService.java new file mode 100644 index 00000000..d3a8a611 --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialLoginService.java @@ -0,0 +1,78 @@ +package com.ruoyi.iot.service; + +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.model.BindLoginBody; +import com.ruoyi.common.core.domain.model.BindRegisterBody; +import me.zhyd.oauth.model.AuthCallback; + +import javax.servlet.http.HttpServletRequest; + +/** + * 第三方登录Service接口 + * 处理登录跳转业务逻辑 + * + * @author json + * @date 2022-04-12 + */ +public interface ISocialLoginService { + + /** + * 第三方登录跳转 + * + * @param source 平台 + * @param httpServletRequest 当前请求 + * @return 跳转路径 + */ + String renderAuth(String source, HttpServletRequest httpServletRequest); + + /** + * 第三方登录callback + * + * @param source 平台 + * @param authCallback 回调参数 + * @param httpServletRequest 当前请求 + * @return 跳转路径 + */ + String callback(String source, AuthCallback authCallback, HttpServletRequest httpServletRequest); + + /** + * 检查是否bindId + * + * @param bindId 绑定id + * @return + */ + AjaxResult checkBindId(String bindId); + + /** + * 获得错误显示 + * + * @param errorId errorId + * @return + */ + AjaxResult getErrorMsg(String errorId); + + /** + * 跳转直接登录 + * + * @param loginId 登录id + * @return + */ + AjaxResult socialLogin(String loginId); + + /** + * 绑定登录api + * + * @param bindLoginBody 绑定账户参数 + * @return + */ + AjaxResult bindLogin(BindLoginBody bindLoginBody); + + /** + * 注册绑定api + * + * @param bindRegisterBody + * @return + */ + AjaxResult bindRegister(BindRegisterBody bindRegisterBody); + +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialPlatformService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialPlatformService.java new file mode 100644 index 00000000..d4cadecf --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialPlatformService.java @@ -0,0 +1,69 @@ +package com.ruoyi.iot.service; + +import java.util.List; +import com.ruoyi.iot.domain.SocialPlatform; + +/** + * 第三方登录平台控制Service接口 + * + * @author json + * @date 2022-04-12 + */ +public interface ISocialPlatformService +{ + /** + * 查询第三方登录平台控制 + * + * @param socialPlatformId 第三方登录平台控制主键 + * @return 第三方登录平台控制 + */ + public SocialPlatform selectSocialPlatformBySocialPlatformId(Long socialPlatformId); + + /** + * 查询第三方登录平台控制 + * + * @param platform 第三方登录平台名称 + * @return 第三方登录平台控制 + */ + public SocialPlatform selectSocialPlatformByPlatform(String platform); + + /** + * 查询第三方登录平台控制列表 + * + * @param socialPlatform 第三方登录平台控制 + * @return 第三方登录平台控制集合 + */ + public List selectSocialPlatformList(SocialPlatform socialPlatform); + + /** + * 新增第三方登录平台控制 + * + * @param socialPlatform 第三方登录平台控制 + * @return 结果 + */ + public int insertSocialPlatform(SocialPlatform socialPlatform); + + /** + * 修改第三方登录平台控制 + * + * @param socialPlatform 第三方登录平台控制 + * @return 结果 + */ + public int updateSocialPlatform(SocialPlatform socialPlatform); + + /** + * 批量删除第三方登录平台控制 + * + * @param socialPlatformIds 需要删除的第三方登录平台控制主键集合 + * @return 结果 + */ + public int deleteSocialPlatformBySocialPlatformIds(Long[] socialPlatformIds); + + /** + * 删除第三方登录平台控制信息 + * + * @param socialPlatformId 第三方登录平台控制主键 + * @return 结果 + */ + public int deleteSocialPlatformBySocialPlatformId(Long socialPlatformId); +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialUserService.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialUserService.java new file mode 100644 index 00000000..b16ebdb1 --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/ISocialUserService.java @@ -0,0 +1,61 @@ +package com.ruoyi.iot.service; + +import java.util.List; +import com.ruoyi.iot.domain.SocialUser; + +/** + * 用户第三方用户信息Service接口 + * + * @author json + * @date 2022-04-18 + */ +public interface ISocialUserService +{ + /** + * 查询用户第三方用户信息 + * + * @param socialUserId 用户第三方用户信息主键 + * @return 用户第三方用户信息 + */ + public SocialUser selectSocialUserBySocialUserId(Long socialUserId); + + /** + * 查询用户第三方用户信息列表 + * + * @param socialUser 用户第三方用户信息 + * @return 用户第三方用户信息集合 + */ + public List selectSocialUserList(SocialUser socialUser); + + /** + * 新增用户第三方用户信息 + * + * @param socialUser 用户第三方用户信息 + * @return 结果 + */ + public int insertSocialUser(SocialUser socialUser); + + /** + * 修改用户第三方用户信息 + * + * @param socialUser 用户第三方用户信息 + * @return 结果 + */ + public int updateSocialUser(SocialUser socialUser); + + /** + * 批量删除用户第三方用户信息 + * + * @param socialUserIds 需要删除的用户第三方用户信息主键集合 + * @return 结果 + */ + public int deleteSocialUserBySocialUserIds(Long[] socialUserIds); + + /** + * 删除用户第三方用户信息信息 + * + * @param socialUserId 用户第三方用户信息主键 + * @return 结果 + */ + public int deleteSocialUserBySocialUserId(Long socialUserId); +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AuthRequestFactoryImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AuthRequestFactoryImpl.java new file mode 100644 index 00000000..57324d81 --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AuthRequestFactoryImpl.java @@ -0,0 +1,69 @@ +package com.ruoyi.iot.service.impl; + +import com.ruoyi.common.enums.SocialPlatformType; +import com.ruoyi.common.exception.ServiceException; +import com.ruoyi.iot.domain.SocialPlatform; +import com.ruoyi.iot.model.login.AuthRequestWrap; +import com.ruoyi.iot.service.IAuthRequestFactory; +import com.ruoyi.iot.service.ISocialPlatformService; +import me.zhyd.oauth.config.AuthConfig; +import me.zhyd.oauth.request.AuthQqRequest; +import me.zhyd.oauth.request.AuthRequest; +import me.zhyd.oauth.request.AuthWeChatMpRequest; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.Locale; + +@Service +public class AuthRequestFactoryImpl implements IAuthRequestFactory { + + private static final Logger log = LoggerFactory.getLogger(AuthRequestFactoryImpl.class); + + @Autowired + private ISocialPlatformService iSocialPlatformService; + + @Autowired + private AuthStateRedisCache authStateRedisCache; + + /** + * 获得对于AUthRequest + * + * @param source 登录方式 + * @return 对应AuthRequest + */ + @Override + public AuthRequestWrap getAuthRequest(String source) { + AuthRequestWrap authRequestWrap = new AuthRequestWrap(); + AuthRequest authRequest; + try { + SocialPlatformType socialPlatformType = SocialPlatformType.valueOf(source.toUpperCase(Locale.ROOT)); + SocialPlatform socialPlatform = iSocialPlatformService.selectSocialPlatformByPlatform(source); + authRequestWrap.setSocialPlatform(socialPlatform); + AuthConfig authConfig = AuthConfig.builder() + .clientId(socialPlatform.getClientId()) + .clientSecret(socialPlatform.getSecretKey()) + .redirectUri(socialPlatform.getRedirectUri()) + .build(); + switch (socialPlatformType) { + case QQ: { + authRequest = new AuthQqRequest(authConfig, authStateRedisCache); + break; + } + case Wechat: { + authRequest = new AuthWeChatMpRequest(authConfig, authStateRedisCache); + break; + } + default: { + throw new ServiceException("source: " + source + ",暂不支持"); + } + } + authRequestWrap.setAuthRequest(authRequest); + return authRequestWrap; + } catch (Exception e) { + throw new ServiceException(e.getMessage()); + } + } +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AuthStateRedisCache.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AuthStateRedisCache.java new file mode 100644 index 00000000..48071a13 --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/AuthStateRedisCache.java @@ -0,0 +1,54 @@ +package com.ruoyi.iot.service.impl; + +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.sign.Md5Utils; +import me.zhyd.oauth.cache.AuthCacheConfig; +import me.zhyd.oauth.cache.AuthStateCache; +import me.zhyd.oauth.utils.AuthStateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.stereotype.Service; + +import java.util.concurrent.TimeUnit; + +/** + * 扩展Redis版的state缓存 + * + * @author json + * @date 2022/04/12 + */ +@Component +public class AuthStateRedisCache implements AuthStateCache { + + @Autowired + private RedisCache redisCache; + + @Override + public void cache(String key, String value) { + redisCache.setCacheObject(key, getValue(value), (int) AuthCacheConfig.timeout, TimeUnit.MILLISECONDS); + } + + @Override + public void cache(String key, String value, long timeout) { + redisCache.setCacheObject(key, getValue(value), (int) timeout, TimeUnit.MILLISECONDS); + } + + @Override + public String get(String key) { + return redisCache.getCacheObject(key); + } + + @Override + public boolean containsKey(String key) { + return redisCache.containsKey(key); + } + + /** + * 自定义state + * @param oldState + * @return state + */ + private String getValue(String oldState) { + return Md5Utils.hash(oldState + System.currentTimeMillis()); + } +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialLoginServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialLoginServiceImpl.java new file mode 100644 index 00000000..194909d7 --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialLoginServiceImpl.java @@ -0,0 +1,353 @@ +package com.ruoyi.iot.service.impl; + +import com.ruoyi.common.constant.Constants; +import com.ruoyi.common.core.domain.AjaxResult; +import com.ruoyi.common.core.domain.entity.SysUser; +import com.ruoyi.common.core.domain.model.BindLoginBody; +import com.ruoyi.common.core.domain.model.BindRegisterBody; +import com.ruoyi.common.core.domain.model.LoginUser; +import com.ruoyi.common.core.redis.RedisCache; +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.common.utils.sign.Md5Utils; +import com.ruoyi.framework.web.service.SysLoginService; +import com.ruoyi.framework.web.service.SysRegisterService; +import com.ruoyi.framework.web.service.TokenService; +import com.ruoyi.iot.domain.SocialPlatform; +import com.ruoyi.iot.domain.SocialUser; +import com.ruoyi.iot.model.login.AuthRequestWrap; +import com.ruoyi.iot.model.login.BindIdValue; +import com.ruoyi.iot.model.login.LoginIdValue; +import com.ruoyi.iot.service.IAuthRequestFactory; +import com.ruoyi.iot.service.ISocialLoginService; +import com.ruoyi.iot.service.ISocialUserService; +import com.ruoyi.system.service.ISysConfigService; +import com.ruoyi.system.service.ISysUserService; +import me.zhyd.oauth.exception.AuthException; +import me.zhyd.oauth.model.AuthCallback; +import me.zhyd.oauth.model.AuthResponse; +import me.zhyd.oauth.model.AuthUser; +import me.zhyd.oauth.utils.AuthStateUtils; +import me.zhyd.oauth.utils.RandomUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import javax.servlet.http.HttpServletRequest; +import java.util.List; +import java.util.concurrent.TimeUnit; + +import static com.ruoyi.common.constant.HttpStatus.NO_MESSAGE_ALERT; +import static com.ruoyi.common.core.domain.AjaxResult.error; + +/** + * 第三方登录Service业务层处理 + * + * @author json + * @date 2022-04-12 + */ +@Service +public class SocialLoginServiceImpl implements ISocialLoginService { + + public static final Integer BIND_EXPIRE_TIME = 60 * 60; + public static final Integer LOGIN_SOCIAL_EXPIRE_TIME = 60; + public static final String ONLINE_STATUS = "0"; //1 offline + public static final String DEL_FLAG = "0"; //1 offline + + //redis key: uuid+source + public static final String BIND_REDIS_KEY = "login:bind:user:"; + //redis key : userId+random 32 + public static final String LOGIN_SOCIAL_REDIS_KEY = "login:social:user:"; + //redis key : msg+ code+currentTime + public static final String LOGIN_ERROR_MSG_REDIS_KEY = "login:error:msg:"; + + public static final String HTTPS = "https://"; + + private static final Logger log = LoggerFactory.getLogger(SocialLoginServiceImpl.class); + + @Autowired + private RedisCache redisCache; + + @Autowired + private ISysConfigService iSysConfigService; + + @Autowired + private TokenService tokenService; + + @Autowired + private SysRegisterService sysRegisterService; + + @Autowired + private SysLoginService sysLoginService; + + @Autowired + private ISysUserService iSysUserService; + + @Autowired + private IAuthRequestFactory iAuthRequestFactory; + + @Autowired + private ISocialUserService iSocialUserService; + + + @Override + public String renderAuth(String source, HttpServletRequest httpServletRequest) { + AuthRequestWrap authRequestWrap = null; + try { + authRequestWrap = iAuthRequestFactory.getAuthRequest(source); + checkSocialPlatform(authRequestWrap.getSocialPlatform()); + return authRequestWrap.getAuthRequest().authorize(AuthStateUtils.createState()); + } catch (AuthException authException) { + //返回错误信息 + log.error("", authException); + if (authRequestWrap != null) { + String errorId = genErrorId(authException.getMessage()); + return authRequestWrap.getSocialPlatform().getErrorMsgUri() + errorId; + } else { + return httpServletRequest.getProtocol() + httpServletRequest.getServerName() + httpServletRequest.getServerPort(); + } + } catch (Exception exception) { + //这类错误 直接不返回,重定向到主页 + log.error("", exception); + return HTTPS + httpServletRequest.getServerName(); + } + + } + + @Override + public String callback(String source, AuthCallback authCallback, HttpServletRequest httpServletRequest) { + AuthRequestWrap authRequestWrap = null; + try { + authRequestWrap = iAuthRequestFactory.getAuthRequest(source); + checkSocialPlatform(authRequestWrap.getSocialPlatform()); + AuthResponse authResponse = authRequestWrap.getAuthRequest().login(authCallback); + String bindId = null; + String loginId = null; + if (authResponse.ok()) { + + SocialUser socialUser = findSocialUser(authResponse.getData().getUuid(), authResponse.getData().getSource()); + createOrUpdateSocialUser(socialUser, authResponse.getData()); + if (socialUser == null) { + //第一次登录 + bindId = genBindId(authResponse.getData()); + } else if (socialUser.getSysUserId() == null || socialUser.getSysUserId() <= 0) { + //初次绑定 + bindId = genBindId(authResponse.getData()); + } else { + //查看是否已经绑定 + SysUser sysUser = iSysUserService.selectUserById(socialUser.getSysUserId()); + if (sysUser == null) { + bindId = genBindId(authResponse.getData()); + } else { + //直接登录跳转 + loginId = genLoginId(sysUser); + } + } + if (StringUtils.isNotEmpty(bindId)) { + return authRequestWrap.getSocialPlatform().getBindUri() + bindId; + } else { + return authRequestWrap.getSocialPlatform().getRedirectLoginUri() + loginId; + } + } else { + log.error("登录授权异常,code:{}, msg:{}", authResponse.getCode(), authResponse.getMsg()); + String errorId = genErrorId(authResponse.getMsg()); + return authRequestWrap.getSocialPlatform().getErrorMsgUri() + errorId; + } + } catch (AuthException authException) { + //返回错误信息 + log.error("", authException); + if (authRequestWrap != null) { + String errorId = genErrorId(authException.getMessage()); + return authRequestWrap.getSocialPlatform().getErrorMsgUri() + errorId; + } else { + return httpServletRequest.getServerName() + httpServletRequest.getServerPort(); + } + } catch (Exception exception) { + log.error("", exception); + return HTTPS + httpServletRequest.getServerName(); + } + + } + + @Override + public AjaxResult checkBindId(String bindId) { + AjaxResult ajax = AjaxResult.success(); + ajax.put("bindAccount", false); + if (StringUtils.isEmpty(bindId)) { + return ajax; + } + BindIdValue bindValue = redisCache.getCacheObject(BIND_REDIS_KEY + bindId); + if (bindValue == null) { + return ajax; + } + ajax.put("bindAccount", true); + return AjaxResult.success(bindId); + } + + @Override + public AjaxResult getErrorMsg(String errorId) { + String errorMsg = redisCache.getCacheObject(LOGIN_ERROR_MSG_REDIS_KEY + errorId); + if (StringUtils.isEmpty(errorMsg)) { + return error(NO_MESSAGE_ALERT, ""); + } else { + return error(errorMsg); + } + } + + @Override + public AjaxResult socialLogin(String loginId) { + AjaxResult ajax = AjaxResult.success(); + String loginKey = LOGIN_SOCIAL_REDIS_KEY + loginId; + LoginIdValue loginIdValue = redisCache.getCacheObject(loginKey); + if (loginIdValue != null) { + //login + String token = sysLoginService.redirectLogin(loginIdValue.getUsername(), loginIdValue.getPassword()); + ajax.put(Constants.TOKEN, token); + } else { + log.info("loginId:{} ", loginId); + return error(NO_MESSAGE_ALERT, "数据错误"); + } + return ajax; + } + + @Override + public AjaxResult bindLogin(BindLoginBody bindLoginBody) { + BindIdValue bindValue = redisCache.getCacheObject(BIND_REDIS_KEY + bindLoginBody.getBindId()); + SocialUser socialUser = findSocialUser(bindValue.getUuid(), bindValue.getSource()); + AjaxResult checkAjax = checkSocialUser(socialUser, bindLoginBody.getBindId()); + if (checkAjax != null) { + return checkAjax; + } + AjaxResult ajax = AjaxResult.success(); + // 生成令牌 + String token = sysLoginService.login(bindLoginBody.getUsername(), bindLoginBody.getPassword(), bindLoginBody.getCode(), + bindLoginBody.getUuid()); + LoginUser loginUser = tokenService.getLoginUserByToken(token); + //绑定和更新 + SocialUser updateSocialUser = new SocialUser(); + updateSocialUser.setSysUserId(loginUser.getUserId()); + updateSocialUser.setSocialUserId(socialUser.getSocialUserId()); + iSocialUserService.updateSocialUser(updateSocialUser); + ajax.put(Constants.TOKEN, token); + redisCache.deleteObject(BIND_REDIS_KEY + bindLoginBody.getBindId()); + return ajax; + } + + @Override + public AjaxResult bindRegister(BindRegisterBody bindRegisterBody) { + if (!("true".equals(iSysConfigService.selectConfigByKey("sys.account.registerUser")))) { + return error("当前系统没有开启注册功能!"); + } + BindIdValue bindValue = redisCache.getCacheObject(BIND_REDIS_KEY + bindRegisterBody.getBindId()); + SocialUser socialUser = findSocialUser(bindValue.getUuid(), bindValue.getSource()); + AjaxResult checkAjax = checkSocialUser(socialUser, bindRegisterBody.getBindId()); + if (checkAjax != null) { + return checkAjax; + } + + AjaxResult ajax = AjaxResult.success(); + String msg = sysRegisterService.register(bindRegisterBody); + if (StringUtils.isEmpty(msg)) { + SysUser sysUser = iSysUserService.selectUserByUserName(bindRegisterBody.getUsername()); + //绑定和更新 + SocialUser updateSocialUser = new SocialUser(); + updateSocialUser.setSysUserId(sysUser.getUserId()); + updateSocialUser.setSocialUserId(socialUser.getSocialUserId()); + iSocialUserService.updateSocialUser(updateSocialUser); + redisCache.deleteObject(BIND_REDIS_KEY + bindRegisterBody.getBindId()); + } + return StringUtils.isEmpty(msg) ? ajax : error(msg); + } + + private void checkSocialPlatform(SocialPlatform socialPlatform) { + if (socialPlatform != null && (!socialPlatform.getStatus().equals(ONLINE_STATUS) || !socialPlatform.getDelFlag().equals(DEL_FLAG))) { + throw new AuthException("当前第三方登录平台被禁用"); + } + } + + public SocialUser findSocialUser(String uuid, String source) { + SocialUser socialUser = new SocialUser(); + socialUser.setSource(source); + socialUser.setUuid(uuid); + List socialUserList = iSocialUserService.selectSocialUserList(socialUser); + return socialUserList == null || socialUserList.isEmpty() ? null : socialUserList.get(0); + + } + + public void createOrUpdateSocialUser(SocialUser socialUser, AuthUser authUser) { + if (socialUser != null) { + //更新数据 + SocialUser updateSocialUser = new SocialUser(); + updateSocialUser.setSocialUserId(socialUser.getSocialUserId()); + replaceSocialUser(updateSocialUser, authUser); + updateSocialUser.setUpdateBy("System"); + updateSocialUser.setUpdateTime(DateUtils.getNowDate()); + iSocialUserService.updateSocialUser(updateSocialUser); + } else { + //创建 + SocialUser saveSocialUser = new SocialUser(); + replaceSocialUser(saveSocialUser, authUser); + saveSocialUser.setDelFlag("0"); + saveSocialUser.setStatus("0"); + saveSocialUser.setCreateBy("System"); + saveSocialUser.setCreateTime(DateUtils.getNowDate()); + iSocialUserService.insertSocialUser(saveSocialUser); + } + } + + private void replaceSocialUser(SocialUser socialUser, AuthUser authUser) { + + socialUser.setUuid(authUser.getUuid()); + socialUser.setSource(authUser.getSource()); + socialUser.setAccessToken(authUser.getToken().getAccessToken()); + //nullable + socialUser.setExpireIn((long) authUser.getToken().getExpireIn()); + socialUser.setRefreshToken(authUser.getToken().getRefreshToken()); + socialUser.setOpenId(authUser.getToken().getOpenId()); + socialUser.setUid(authUser.getToken().getUid()); + socialUser.setAccessCode(authUser.getToken().getAccessCode()); + socialUser.setUnionId(authUser.getToken().getUnionId()); + socialUser.setCode(authUser.getToken().getCode()); + socialUser.setAvatar(authUser.getAvatar()); + socialUser.setUsername(authUser.getUsername()); + socialUser.setNickname(authUser.getNickname()); + } + + private String genBindId(AuthUser authUser) { + String bindId = Md5Utils.hash(authUser.getUuid() + authUser.getSource()); + String key = BIND_REDIS_KEY + bindId; + BindIdValue bindIdValue = new BindIdValue(); + bindIdValue.setSource(authUser.getSource()); + bindIdValue.setUuid(authUser.getUuid()); + redisCache.setCacheObject(key, bindIdValue, BIND_EXPIRE_TIME, TimeUnit.SECONDS); + return bindId; + } + + private String genLoginId(SysUser sysUser) { + String loginId = Md5Utils.hash(sysUser.getUserId() + RandomUtil.randomString(32)); + String key = LOGIN_SOCIAL_REDIS_KEY + loginId; + LoginIdValue loginIdValue = new LoginIdValue(); + loginIdValue.setPassword(sysUser.getPassword()); + loginIdValue.setUsername(sysUser.getUserName()); + redisCache.setCacheObject(key, loginIdValue, LOGIN_SOCIAL_EXPIRE_TIME, TimeUnit.SECONDS); + return loginId; + } + + private String genErrorId(String msg) { + String errorId = Md5Utils.hash(msg + RandomUtil.randomString(32)); + String key = LOGIN_ERROR_MSG_REDIS_KEY + errorId; + redisCache.setCacheObject(key, msg, LOGIN_SOCIAL_EXPIRE_TIME, TimeUnit.SECONDS); + return errorId; + } + + private AjaxResult checkSocialUser(SocialUser socialUser, String bindId) { + if (socialUser == null) { + log.info("bindId不存在, bindId: {}", bindId); + return error("绑定账户不存在"); + } else { + return null; + } + } + +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialPlatformServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialPlatformServiceImpl.java new file mode 100644 index 00000000..0ba91040 --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialPlatformServiceImpl.java @@ -0,0 +1,103 @@ +package com.ruoyi.iot.service.impl; + +import com.ruoyi.common.utils.DateUtils; +import com.ruoyi.iot.domain.SocialPlatform; +import com.ruoyi.iot.mapper.SocialPlatformMapper; +import com.ruoyi.iot.service.ISocialPlatformService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 第三方登录平台控制Service业务层处理 + * + * @author kerwincui + * @date 2022-04-11 + */ +@Service +public class SocialPlatformServiceImpl implements ISocialPlatformService +{ + @Autowired + private SocialPlatformMapper socialPlatformMapper; + + /** + * 查询第三方登录平台控制 + * + * @param socialPlatformId 第三方登录平台控制主键 + * @return 第三方登录平台控制 + */ + @Override + public SocialPlatform selectSocialPlatformBySocialPlatformId(Long socialPlatformId) + { + return socialPlatformMapper.selectSocialPlatformBySocialPlatformId(socialPlatformId); + } + + @Override + public SocialPlatform selectSocialPlatformByPlatform(String platform) { + return socialPlatformMapper.selectSocialPlatformByPlatform(platform); + } + + /** + * 查询第三方登录平台控制列表 + * + * @param socialPlatform 第三方登录平台控制 + * @return 第三方登录平台控制 + */ + @Override + public List selectSocialPlatformList(SocialPlatform socialPlatform) + { + return socialPlatformMapper.selectSocialPlatformList(socialPlatform); + } + + /** + * 新增第三方登录平台控制 + * + * @param socialPlatform 第三方登录平台控制 + * @return 结果 + */ + @Override + public int insertSocialPlatform(SocialPlatform socialPlatform) + { + socialPlatform.setCreateTime(DateUtils.getNowDate()); + socialPlatform.setDelFlag("0"); + return socialPlatformMapper.insertSocialPlatform(socialPlatform); + } + + /** + * 修改第三方登录平台控制 + * + * @param socialPlatform 第三方登录平台控制 + * @return 结果 + */ + @Override + public int updateSocialPlatform(SocialPlatform socialPlatform) + { + socialPlatform.setUpdateTime(DateUtils.getNowDate()); + return socialPlatformMapper.updateSocialPlatform(socialPlatform); + } + + /** + * 批量删除第三方登录平台控制 + * + * @param socialPlatformIds 需要删除的第三方登录平台控制主键 + * @return 结果 + */ + @Override + public int deleteSocialPlatformBySocialPlatformIds(Long[] socialPlatformIds) + { + return socialPlatformMapper.deleteSocialPlatformBySocialPlatformIds(socialPlatformIds); + } + + /** + * 删除第三方登录平台控制信息 + * + * @param socialPlatformId 第三方登录平台控制主键 + * @return 结果 + */ + @Override + public int deleteSocialPlatformBySocialPlatformId(Long socialPlatformId) + { + return socialPlatformMapper.deleteSocialPlatformBySocialPlatformId(socialPlatformId); + } +} diff --git a/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialUserServiceImpl.java b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialUserServiceImpl.java new file mode 100644 index 00000000..2dc1beec --- /dev/null +++ b/springboot/wumei-iot/src/main/java/com/ruoyi/iot/service/impl/SocialUserServiceImpl.java @@ -0,0 +1,96 @@ +package com.ruoyi.iot.service.impl; + +import java.util.List; +import com.ruoyi.common.utils.DateUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; +import com.ruoyi.iot.mapper.SocialUserMapper; +import com.ruoyi.iot.domain.SocialUser; +import com.ruoyi.iot.service.ISocialUserService; + +/** + * 用户第三方用户信息Service业务层处理 + * + * @author json + * @date 2022-04-18 + */ +@Service +public class SocialUserServiceImpl implements ISocialUserService +{ + @Autowired + private SocialUserMapper socialUserMapper; + + /** + * 查询用户第三方用户信息 + * + * @param socialUserId 用户第三方用户信息主键 + * @return 用户第三方用户信息 + */ + @Override + public SocialUser selectSocialUserBySocialUserId(Long socialUserId) + { + return socialUserMapper.selectSocialUserBySocialUserId(socialUserId); + } + + /** + * 查询用户第三方用户信息列表 + * + * @param socialUser 用户第三方用户信息 + * @return 用户第三方用户信息 + */ + @Override + public List selectSocialUserList(SocialUser socialUser) + { + return socialUserMapper.selectSocialUserList(socialUser); + } + + /** + * 新增用户第三方用户信息 + * + * @param socialUser 用户第三方用户信息 + * @return 结果 + */ + @Override + public int insertSocialUser(SocialUser socialUser) + { + socialUser.setCreateTime(DateUtils.getNowDate()); + return socialUserMapper.insertSocialUser(socialUser); + } + + /** + * 修改用户第三方用户信息 + * + * @param socialUser 用户第三方用户信息 + * @return 结果 + */ + @Override + public int updateSocialUser(SocialUser socialUser) + { + socialUser.setUpdateTime(DateUtils.getNowDate()); + return socialUserMapper.updateSocialUser(socialUser); + } + + /** + * 批量删除用户第三方用户信息 + * + * @param socialUserIds 需要删除的用户第三方用户信息主键 + * @return 结果 + */ + @Override + public int deleteSocialUserBySocialUserIds(Long[] socialUserIds) + { + return socialUserMapper.deleteSocialUserBySocialUserIds(socialUserIds); + } + + /** + * 删除用户第三方用户信息信息 + * + * @param socialUserId 用户第三方用户信息主键 + * @return 结果 + */ + @Override + public int deleteSocialUserBySocialUserId(Long socialUserId) + { + return socialUserMapper.deleteSocialUserBySocialUserId(socialUserId); + } +} diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/SocialPlatformMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/SocialPlatformMapper.xml new file mode 100644 index 00000000..3cd74e33 --- /dev/null +++ b/springboot/wumei-iot/src/main/resources/mapper/iot/SocialPlatformMapper.xml @@ -0,0 +1,141 @@ + + + + + + + + + + + + + + + + + + + + + + + + select social_platform_id, + platform, + status, + client_id, + secret_key, + redirect_uri, + del_flag, + create_by, + create_time, + update_time, + update_by, + remark, + bind_uri, + redirect_login_uri, + error_msg_uri + from iot_social_platform + + + + + + + + + + insert into iot_social_platform + + platform, + status, + client_id, + secret_key, + redirect_uri, + del_flag, + create_by, + create_time, + update_time, + update_by, + remark, + bind_uri, + redirect_login_uri, + error_msg_uri, + + + #{platform}, + #{status}, + #{clientId}, + #{secretKey}, + #{redirectUri}, + #{delFlag}, + #{createBy}, + #{createTime}, + #{updateTime}, + #{updateBy}, + #{remark}, + #{bindUri}, + #{redirectLoginUri}, + #{errorMsgUri}, + + + + + update iot_social_platform + + platform = #{platform}, + status = #{status}, + client_id = #{clientId}, + secret_key = #{secretKey}, + redirect_uri = #{redirectUri}, + del_flag = #{delFlag}, + create_by = #{createBy}, + create_time = #{createTime}, + update_time = #{updateTime}, + update_by = #{updateBy}, + remark = #{remark}, + bind_uri = #{bindUri}, + redirect_login_uri = #{redirectLoginUri}, + + error_msg_uri = #{errorMsgUri}, + + where social_platform_id = #{socialPlatformId} + + + + delete + from iot_social_platform + where social_platform_id = #{socialPlatformId} + + + + delete from iot_social_platform where social_platform_id in + + #{socialPlatformId} + + + \ No newline at end of file diff --git a/springboot/wumei-iot/src/main/resources/mapper/iot/SocialUserMapper.xml b/springboot/wumei-iot/src/main/resources/mapper/iot/SocialUserMapper.xml new file mode 100644 index 00000000..a5f479ba --- /dev/null +++ b/springboot/wumei-iot/src/main/resources/mapper/iot/SocialUserMapper.xml @@ -0,0 +1,219 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + select social_user_id, + uuid, + source, + access_token, + expire_in, + refresh_token, + open_id, + uid, + access_code, + union_id, + scope, + token_type, + id_token, + mac_algorithm, + mac_key, + code, + oauth_token, + oauth_token_secret, + create_time, + create_by, + update_time, + update_by, + del_flag, + status, + sys_user_id, + username, + nickname, + avatar, + gender + from iot_social_user + + + + + + + + insert into iot_social_user + + uuid, + source, + access_token, + expire_in, + refresh_token, + open_id, + uid, + access_code, + union_id, + scope, + token_type, + id_token, + mac_algorithm, + mac_key, + code, + oauth_token, + oauth_token_secret, + create_time, + create_by, + update_time, + update_by, + del_flag, + status, + sys_user_id, + username, + nickname, + avatar, + gender, + + + #{uuid}, + #{source}, + #{accessToken}, + #{expireIn}, + #{refreshToken}, + #{openId}, + #{uid}, + #{accessCode}, + #{unionId}, + #{scope}, + #{tokenType}, + #{idToken}, + #{macAlgorithm}, + #{macKey}, + #{code}, + #{oauthToken}, + #{oauthTokenSecret}, + #{createTime}, + #{createBy}, + #{updateTime}, + #{updateBy}, + #{delFlag}, + #{status}, + #{sysUserId}, + #{username}, + #{nickname}, + #{avatar}, + #{gender}, + + + + + update iot_social_user + + uuid = #{uuid}, + source = #{source}, + access_token = #{accessToken}, + expire_in = #{expireIn}, + refresh_token = #{refreshToken}, + open_id = #{openId}, + uid = #{uid}, + access_code = #{accessCode}, + union_id = #{unionId}, + scope = #{scope}, + token_type = #{tokenType}, + id_token = #{idToken}, + mac_algorithm = #{macAlgorithm}, + mac_key = #{macKey}, + code = #{code}, + oauth_token = #{oauthToken}, + oauth_token_secret = #{oauthTokenSecret}, + create_time = #{createTime}, + create_by = #{createBy}, + update_time = #{updateTime}, + update_by = #{updateBy}, + del_flag = #{delFlag}, + status = #{status}, + sys_user_id = #{sysUserId}, + username = #{username}, + nickname = #{nickname}, + avatar = #{avatar}, + gender = #{gender}, + + where social_user_id = #{socialUserId} + + + + delete + from iot_social_user + where social_user_id = #{socialUserId} + + + + delete from iot_social_user where social_user_id in + + #{socialUserId} + + + \ No newline at end of file diff --git a/vue/src/api/iot/platform.js b/vue/src/api/iot/platform.js new file mode 100644 index 00000000..697728be --- /dev/null +++ b/vue/src/api/iot/platform.js @@ -0,0 +1,44 @@ +import request from '@/utils/request' + +// 查询第三方登录平台控制列表 +export function listPlatform(query) { + return request({ + url: '/iot/platform/list', + method: 'get', + params: query + }) +} + +// 查询第三方登录平台控制详细 +export function getPlatform(socialPlatformId) { + return request({ + url: '/iot/platform/' + socialPlatformId, + method: 'get' + }) +} + +// 新增第三方登录平台控制 +export function addPlatform(data) { + return request({ + url: '/iot/platform', + method: 'post', + data: data + }) +} + +// 修改第三方登录平台控制 +export function updatePlatform(data) { + return request({ + url: '/iot/platform', + method: 'put', + data: data + }) +} + +// 删除第三方登录平台控制 +export function delPlatform(socialPlatformId) { + return request({ + url: '/iot/platform/' + socialPlatformId, + method: 'delete' + }) +} diff --git a/vue/src/api/login.js b/vue/src/api/login.js index 649f59c8..1e1bea0b 100644 --- a/vue/src/api/login.js +++ b/vue/src/api/login.js @@ -56,4 +56,59 @@ export function getCodeImg() { method: 'get', timeout: 20000 }) -} \ No newline at end of file +} + +//查看是否存在bindId +export function checkBindId(bindId) { + return request({ + url: '/auth/checkBindId/' + bindId, + method: 'get', + }) +} + +//查看是否存在errorId +export function getErrorMsg(errorId) { + return request({ + url: '/auth/getErrorMsg/' + errorId, + method: 'get', + }) +} + +// 登录方法 +export function bindLogin(username, password, code, uuid, bindId) { + const data = { + username, + password, + code, + uuid, + bindId + } + return request({ + url: '/auth/bind/login', + headers: { + isToken: false + }, + method: 'post', + data: data + }) +} + +// 注册方法 +export function bindRegister(data) { + return request({ + url: '/auth/bind/register', + headers: { + isToken: false + }, + method: 'post', + data: data + }) +} + +//跳转登录 +export function redirectLogin(loginId) { + return request({ + url: '/auth/login/' + loginId, + method: 'get', + }) +} diff --git a/vue/src/store/modules/user.js b/vue/src/store/modules/user.js index 0e451572..471191ff 100644 --- a/vue/src/store/modules/user.js +++ b/vue/src/store/modules/user.js @@ -1,5 +1,5 @@ -import { login, logout, getInfo } from '@/api/login' -import { getToken, setToken, removeToken } from '@/utils/auth' +import {bindLogin, getInfo, login, logout, redirectLogin} from '@/api/login' +import {getToken, removeToken, setToken} from '@/utils/auth' const user = { state: { @@ -30,13 +30,36 @@ const user = { actions: { // 登录 - Login({ commit }, userInfo) { + Login({commit}, userInfo) { const username = userInfo.username.trim() const password = userInfo.password const code = userInfo.code const uuid = userInfo.uuid + const bindId = userInfo.bindId; return new Promise((resolve, reject) => { - login(username, password, code, uuid).then(res => { + if (bindId === undefined || bindId === "") { + login(username, password, code, uuid).then(res => { + setToken(res.token) + commit('SET_TOKEN', res.token) + resolve() + }).catch(error => { + reject(error) + }) + } else { + bindLogin(username, password, code, uuid, bindId).then(res => { + setToken(res.token) + commit('SET_TOKEN', res.token) + resolve() + }).catch(error => { + reject(error) + }) + } + }) + }, + + RedirectLogin({commit}, loginId) { + return new Promise((resolve, reject) => { + redirectLogin(loginId).then(res => { setToken(res.token) commit('SET_TOKEN', res.token) resolve() @@ -47,7 +70,7 @@ const user = { }, // 获取用户信息 - GetInfo({ commit, state }) { + GetInfo({commit, state}) { return new Promise((resolve, reject) => { getInfo().then(res => { const user = res.user @@ -68,7 +91,7 @@ const user = { }, // 退出系统 - LogOut({ commit, state }) { + LogOut({commit, state}) { return new Promise((resolve, reject) => { logout(state.token).then(() => { commit('SET_TOKEN', '') @@ -83,7 +106,7 @@ const user = { }, // 前端 登出 - FedLogOut({ commit }) { + FedLogOut({commit}) { return new Promise(resolve => { commit('SET_TOKEN', '') removeToken() diff --git a/vue/src/utils/request.js b/vue/src/utils/request.js index 1acd9416..49f1accb 100644 --- a/vue/src/utils/request.js +++ b/vue/src/utils/request.js @@ -1,10 +1,10 @@ import axios from 'axios' -import { Notification, MessageBox, Message, Loading } from 'element-ui' +import {Loading, Message, MessageBox, Notification} from 'element-ui' import store from '@/store' -import { getToken } from '@/utils/auth' +import {getToken} from '@/utils/auth' import errorCode from '@/utils/errorCode' -import { tansParams, blobValidate } from "@/utils/ruoyi"; -import { saveAs } from 'file-saver' +import {blobValidate, tansParams} from "@/utils/ruoyi"; +import {saveAs} from 'file-saver' let downloadLoadingInstance; @@ -65,6 +65,8 @@ service.interceptors.response.use(res => { type: 'error' }) return Promise.reject(new Error(msg)) + } else if (code === 502) { + return Promise.reject('error') } else if (code !== 200) { Notification.error({ title: msg diff --git a/vue/src/views/iot/platform/index.vue b/vue/src/views/iot/platform/index.vue new file mode 100644 index 00000000..c2ff290f --- /dev/null +++ b/vue/src/views/iot/platform/index.vue @@ -0,0 +1,366 @@ + + + diff --git a/vue/src/views/iot/product/product-things-model.vue b/vue/src/views/iot/product/product-things-model.vue index 088fe600..9b671012 100644 --- a/vue/src/views/iot/product/product-things-model.vue +++ b/vue/src/views/iot/product/product-things-model.vue @@ -39,7 +39,7 @@ - + @@ -355,6 +355,7 @@ export default { this.form.datatype = "integer" this.form.specs = { enumList: [], + arrayType: "int" }; }, /** 修改按钮操作 */ @@ -543,8 +544,6 @@ export default { value: "", text: "" }]; - } else if (val == "array") { - this.form.specs.arrayType = "int"; } }, /** 添加枚举项 */ diff --git a/vue/src/views/iot/template/index.vue b/vue/src/views/iot/template/index.vue index 51077152..0d5e8eb8 100644 --- a/vue/src/views/iot/template/index.vue +++ b/vue/src/views/iot/template/index.vue @@ -63,7 +63,7 @@ - + @@ -75,8 +75,8 @@ @@ -278,17 +278,17 @@ export default { this.init(); }, methods: { - init(){ - if (this.$store.state.user.roles.indexOf("admin") !== -1){ - this.canEdit = true - } + init() { + if (this.$store.state.user.roles.indexOf("admin") !== -1) { + this.canEdit = true + } }, /** 查询通用物模型列表 */ getList() { this.loading = true; - if (this.$store.state.user.roles.indexOf("admin") === -1){ - this.queryParams.tenantName = this.$store.state.user.name - } + if (this.$store.state.user.roles.indexOf("admin") === -1) { + this.queryParams.tenantName = this.$store.state.user.name + } listTemplate(this.queryParams).then((response) => { this.templateList = response.rows; this.total = response.total; @@ -350,6 +350,7 @@ export default { this.form.datatype = "integer" this.form.specs = { enumList: [], + arrayType: "int" }; }, /** 修改按钮操作 */ @@ -377,8 +378,8 @@ export default { this.form.isMonitor = 0; this.form.isTop = 0; } - // 添加通用物模型的修改者 - this.form.updateBy = this.$store.state.user.name + // 添加通用物模型的修改者 + this.form.updateBy = this.$store.state.user.name updateTemplate(this.form).then((response) => { this.$modal.msgSuccess("修改成功"); this.open = false; @@ -428,15 +429,15 @@ export default { ); }, // 类型改变 - typeChange(label){ - if(label==2 || label==3){ - this.form.isMonitor=0; + typeChange(label) { + if (label == 2 || label == 3) { + this.form.isMonitor = 0; } }, // 实时监测改变 - changeMonitor(isMonitor){ - if(isMonitor==1 && this.form.datatype!="integer" && this.form.datatype!="decimal"){ - this.form.datatype="integer"; + changeMonitor(isMonitor) { + if (isMonitor == 1 && this.form.datatype != "integer" && this.form.datatype != "decimal") { + this.form.datatype = "integer"; } }, // 格式化物模型 @@ -467,8 +468,6 @@ export default { value: "", text: "" }]; - } else if (val == "array") { - this.form.specs.arrayType = "int"; } }, /** 添加枚举项 */ diff --git a/vue/src/views/login.vue b/vue/src/views/login.vue index e5831293..0e4156b3 100644 --- a/vue/src/views/login.vue +++ b/vue/src/views/login.vue @@ -1,292 +1,369 @@ diff --git a/vue/src/views/register.vue b/vue/src/views/register.vue index 022c08c8..c5af4ca3 100644 --- a/vue/src/views/register.vue +++ b/vue/src/views/register.vue @@ -1,270 +1,360 @@