From bb2cdebac3b831282f9d48ad1a0305f96ae404c8 Mon Sep 17 00:00:00 2001 From: LemonTree Date: Wed, 20 Apr 2022 18:30:27 +0800 Subject: [PATCH] =?UTF-8?q?[=E5=8A=9F=E8=83=BD]=EF=BC=9A1=E3=80=81?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0http=E9=80=9A=E7=94=A8=E6=8E=A5=E5=8F=A3fores?= =?UTF-8?q?t=202=E3=80=81=E5=BC=95=E5=85=A5justoauth=20=E5=A4=84=E7=90=86?= =?UTF-8?q?=E7=AC=AC=E4=B8=89=E6=96=B9=E7=99=BB=E5=BD=95=203=E3=80=81?= =?UTF-8?q?=E5=A4=A7=E8=87=B4=E5=AE=8C=E6=88=90qq=E7=99=BB=E5=BD=95?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=204=E3=80=81=E5=89=8D=E7=AB=AF=E7=95=8C?= =?UTF-8?q?=E9=9D=A2=E4=BF=AE=E6=94=B9=E9=80=82=E9=85=8D=E7=AC=AC=E4=B8=89?= =?UTF-8?q?=E6=96=B9=E7=99=BB=E5=BD=95=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- springboot/.gitignore | 1 + springboot/pom.xml | 22 +- .../src/main/resources/application-druid.yml | 40 +- .../src/main/resources/application.yml | 54 +- .../com/ruoyi/common/constant/HttpStatus.java | 5 + .../ruoyi/common/core/redis/RedisCache.java | 13 +- .../framework/config/SecurityConfig.java | 2 +- .../web/service/SysLoginService.java | 33 ++ .../framework/web/service/TokenService.java | 71 +-- springboot/wumei-iot/pom.xml | 13 + vue/src/api/login.js | 57 +- vue/src/store/modules/user.js | 37 +- vue/src/utils/request.js | 10 +- vue/src/views/login.vue | 555 ++++++++++-------- vue/src/views/register.vue | 522 +++++++++------- 15 files changed, 875 insertions(+), 560 deletions(-) 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 ca08ffff..bc6d9ed7 100644 --- a/springboot/wumei-admin/src/main/resources/application-druid.yml +++ b/springboot/wumei-admin/src/main/resources/application-druid.yml @@ -9,14 +9,14 @@ spring: url: jdbc:mysql://localhost/wumei-smart?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8 username: root password: wumei-smart -# password: 123456 + # password: 123456 # 从库数据源 slave: - # 从数据源开关/默认关闭 - enabled: false - url: - username: - password: + # 从数据源开关/默认关闭 + enabled: false + url: + username: + password: # 初始连接数 initialSize: 5 # 最小连接池数量 @@ -27,27 +27,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 +55,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 2dce8904..d7a25535 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/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-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/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/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 @@