diff --git a/pom.xml b/pom.xml index 9148a28..71efd32 100644 --- a/pom.xml +++ b/pom.xml @@ -97,12 +97,69 @@ hutool-all 5.8.11 + + + com.auth0 + java-jwt + 4.4.0 + + + + io.jsonwebtoken + jjwt + 0.9.1 + + + + org.springframework.boot + spring-boot-starter-security + + + cn.hutool + hutool-all + 5.8.9 + + + + javax.xml.bind + jaxb-api + 2.3.1 + + + com.github.xiaoymin + knife4j-openapi2-spring-boot-starter + 4.1.0 + + + org.apache.commons + commons-lang3 + 3.4 + + + org.springframework.boot + spring-boot-starter-amqp + + + + com.aliyun + aliyun-java-sdk-core + 4.6.1 + + + com.aliyun + aliyun-java-sdk-dysmsapi + 2.2.1 + + + org.springframework.boot + spring-boot-starter-data-redis + - + diff --git a/src/main/java/com/teaching/backend/annotation/test1.java b/src/main/java/com/teaching/backend/annotation/test1.java deleted file mode 100644 index 20db4c6..0000000 --- a/src/main/java/com/teaching/backend/annotation/test1.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.teaching.backend.annotation; - -/** - * @Author:youhang - * @Date:2024-05-30-18:20 - * @Description: - */ -public class test1 { -} diff --git a/src/main/java/com/teaching/backend/aop/test1.java b/src/main/java/com/teaching/backend/aop/test1.java deleted file mode 100644 index 0b524ed..0000000 --- a/src/main/java/com/teaching/backend/aop/test1.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.teaching.backend.aop; - -/** - * @Author:youhang - * @Date:2024-05-30-18:20 - * @Description: - */ -public class test1 { -} diff --git a/src/main/java/com/teaching/backend/api/CommonConstant.java b/src/main/java/com/teaching/backend/api/CommonConstant.java new file mode 100644 index 0000000..43bdf3e --- /dev/null +++ b/src/main/java/com/teaching/backend/api/CommonConstant.java @@ -0,0 +1,377 @@ +package com.teaching.backend.api; + +public interface CommonConstant { + + + + + + /** + * 未查询到信息 + */ + public String delete_batch_success = "批量删除成功!"; + + /** + * 未查询到信息 + */ + public String detail_failed = "未查询到信息"; + /** + * 修改失败标志 + */ + public String update_failed = "修改失败"; + /** + * 修改失败标志 + */ + public String update_success = "修改成功"; + + /** + * + * message: 添加成功 + */ + public static final String MESSAGE_add_SUCCESS = "添加成功"; + + /** + * + * message: 添加成功 + */ + public static final String MESSAGE_add__FAILED = "添加失败"; + + /** + * + * message: 添加成功 + */ + public static final String MESSAGE_QUERY_SUCCESS = "查询成功"; + /** + * + * message:删除成功 + */ + public static final String MESSAGE_DELETE_SUCCESS = "删除成功"; + /** + * + * message:删除失败 + */ + public static final String MESSAGE_DELETE_FAILED = "删除失败"; + + /** + * 正常状态 + */ + public static final Integer STATUS_NORMAL = 0; + + /** + * 禁用状态 + */ + public static final Integer STATUS_DISABLE = -1; + + /** + * 删除标志 + */ + public static final Integer DEL_FLAG_1 = 1; + + /** + * 未删除 + */ + public static final Integer DEL_FLAG_0 = 0; + + /** + * 系统日志类型: 登录 + */ + public static final int LOG_TYPE_1 = 1; + + /** + * 系统日志类型: 操作 + */ + public static final int LOG_TYPE_2 = 2; + + /** + * 操作日志类型: 查询 + */ + public static final int OPERATE_TYPE_1 = 1; + + /** + * 操作日志类型: 添加 + */ + public static final int OPERATE_TYPE_2 = 2; + + /** + * 操作日志类型: 更新 + */ + public static final int OPERATE_TYPE_3 = 3; + + /** + * 操作日志类型: 删除 + */ + public static final int OPERATE_TYPE_4 = 4; + + /** + * 操作日志类型: 倒入 + */ + public static final int OPERATE_TYPE_5 = 5; + + /** + * 操作日志类型: 导出 + */ + public static final int OPERATE_TYPE_6 = 6; + + + /** {@code 500 Server Error} (HTTP/1.0 - RFC 1945) */ + public static final Integer SC_INTERNAL_SERVER_ERROR_500 = 500; + /** {@code 200 OK} (HTTP/1.0 - RFC 1945) */ + public static final Integer SC_OK_200 = 200; + + /**访问权限认证未通过 510*/ + public static final Integer SC_JEECG_NO_AUTHZ=510; + + /** 登录用户Shiro权限缓存KEY前缀 */ + public static String PREFIX_USER_SHIRO_CACHE = "shiro:cache:org.jeecg.config.shiro.ShiroRealm.authorizationCache:"; + /** 登录用户Token令牌缓存KEY前缀 */ + public static final String PREFIX_USER_TOKEN = "prefix_user_token_"; + /** Token缓存时间:3600秒即一小时 */ + public static final int TOKEN_EXPIRE_TIME = 3600; + + + /** + * 0:一级菜单 + */ + public static final Integer MENU_TYPE_0 = 0; + /** + * 1:子菜单 + */ + public static final Integer MENU_TYPE_1 = 1; + /** + * 2:按钮权限 + */ + public static final Integer MENU_TYPE_2 = 2; + + /**通告对象类型(USER:指定用户,ALL:全体用户)*/ + public static final String MSG_TYPE_UESR = "USER"; + public static final String MSG_TYPE_ALL = "ALL"; + + /**发布状态(0未发布,1已发布,2已撤销)*/ + public static final String NO_SEND = "0"; + public static final String HAS_SEND = "1"; + public static final String HAS_CANCLE = "2"; + + /**阅读状态(0未读,1已读)*/ + public static final String HAS_READ_FLAG = "1"; + public static final String NO_READ_FLAG = "0"; + + /**优先级(L低,M中,H高)*/ + public static final String PRIORITY_L = "L"; + public static final String PRIORITY_M = "M"; + public static final String PRIORITY_H = "H"; + + /** + * 短信模板方式 0 .登录模板、1.注册模板、2.忘记密码模板 + */ + public static final String SMS_TPL_TYPE_0 = "0"; + public static final String SMS_TPL_TYPE_1 = "1"; + public static final String SMS_TPL_TYPE_2 = "2"; + + /** + * 状态(0无效1有效) + */ + public static final String STATUS_0 = "0"; + public static final String STATUS_1 = "1"; + + /** + * 同步工作流引擎1同步0不同步 + */ + public static final Integer ACT_SYNC_1 = 1; + public static final Integer ACT_SYNC_0 = 0; + + /** + * 消息类型1:通知公告2:系统消息 + */ + public static final String MSG_CATEGORY_1 = "1"; + public static final String MSG_CATEGORY_2 = "2"; + + /** + * 是否配置菜单的数据权限 1是0否 + */ + public static final Integer RULE_FLAG_0 = 0; + public static final Integer RULE_FLAG_1 = 1; + + /** + * 是否用户已被冻结 1正常(解冻) 2冻结 + */ + public static final Integer USER_UNFREEZE = 1; + public static final Integer USER_FREEZE = 2; + + /**字典翻译文本后缀*/ + public static final String DICT_TEXT_SUFFIX = "_dictText"; + + /** + * 表单设计器主表类型 + */ + public static final Integer DESIGN_FORM_TYPE_MAIN = 1; + + /** + * 表单设计器子表表类型 + */ + public static final Integer DESIGN_FORM_TYPE_SUB = 2; + + /** + * 表单设计器URL授权通过 + */ + public static final Integer DESIGN_FORM_URL_STATUS_PASSED = 1; + + /** + * 表单设计器URL授权未通过 + */ + public static final Integer DESIGN_FORM_URL_STATUS_NOT_PASSED = 2; + + /** + * 表单设计器新增 Flag + */ + public static final String DESIGN_FORM_URL_TYPE_ADD = "add"; + /** + * 表单设计器修改 Flag + */ + public static final String DESIGN_FORM_URL_TYPE_EDIT = "edit"; + /** + * 表单设计器详情 Flag + */ + public static final String DESIGN_FORM_URL_TYPE_DETAIL = "detail"; + /** + * 表单设计器复用数据 Flag + */ + public static final String DESIGN_FORM_URL_TYPE_REUSE = "reuse"; + /** + * 表单设计器编辑 Flag (已弃用) + */ + public static final String DESIGN_FORM_URL_TYPE_VIEW = "view"; + + /** + * online参数值设置(是:Y, 否:N) + */ + public static final String ONLINE_PARAM_VAL_IS_TURE = "Y"; + public static final String ONLINE_PARAM_VAL_IS_FALSE = "N"; + + /** + * 文件上传类型(本地:local,Minio:minio,阿里云:alioss) + */ + public static final String UPLOAD_TYPE_LOCAL = "local"; + public static final String UPLOAD_TYPE_MINIO = "minio"; + public static final String UPLOAD_TYPE_OSS = "alioss"; + + /** + * 文档上传自定义桶名称 + */ + public static final String UPLOAD_CUSTOM_BUCKET = "eoafile"; + /** + * 文档上传自定义路径 + */ + public static final String UPLOAD_CUSTOM_PATH = "eoafile"; + /** + * 文件外链接有效天数 + */ + public static final Integer UPLOAD_EFFECTIVE_DAYS = 1; + + /** + * 员工身份 (1:普通员工 2:上级) + */ + public static final Integer USER_IDENTITY_1 = 1; + public static final Integer USER_IDENTITY_2 = 2; + + /** sys_user 表 username 唯一键索引 */ + public static final String SQL_INDEX_UNIQ_SYS_USER_USERNAME = "uniq_sys_user_username"; + /** sys_user 表 work_no 唯一键索引 */ + public static final String SQL_INDEX_UNIQ_SYS_USER_WORK_NO = "uniq_sys_user_work_no"; + /** sys_user 表 phone 唯一键索引 */ + public static final String SQL_INDEX_UNIQ_SYS_USER_PHONE = "uniq_sys_user_phone"; + /** sys_user 表 email 唯一键索引 */ + public static final String SQL_INDEX_UNIQ_SYS_USER_EMAIL = "uniq_sys_user_email"; + /** sys_quartz_job 表 job_class_name 唯一键索引 */ + public static final String SQL_INDEX_UNIQ_JOB_CLASS_NAME = "uniq_job_class_name"; + /** sys_position 表 code 唯一键索引 */ + public static final String SQL_INDEX_UNIQ_CODE = "uniq_code"; + /** sys_role 表 code 唯一键索引 */ + public static final String SQL_INDEX_UNIQ_SYS_ROLE_CODE = "uniq_sys_role_role_code"; + /** sys_depart 表 code 唯一键索引 */ + public static final String SQL_INDEX_UNIQ_DEPART_ORG_CODE = "uniq_depart_org_code"; + /** + * 在线聊天 是否为默认分组 + */ + public static final String IM_DEFAULT_GROUP = "1"; + /** + * 在线聊天 图片文件保存路径 + */ + public static final String IM_UPLOAD_CUSTOM_PATH = "imfile"; + /** + * 在线聊天 用户状态 + */ + public static final String IM_STATUS_ONLINE = "online"; + + /** + * 在线聊天 SOCKET消息类型 + */ + public static final String IM_SOCKET_TYPE = "chatMessage"; + + /** + * 在线聊天 是否开启默认添加好友 1是 0否 + */ + public static final String IM_DEFAULT_ADD_FRIEND = "1"; + + /** + * 在线聊天 用户好友缓存前缀 + */ + public static final String IM_PREFIX_USER_FRIEND_CACHE = "sys:cache:im:im_prefix_user_friend_"; + + /** + * 考勤补卡业务状态 (1:同意 2:不同意) + */ + public static final String SIGN_PATCH_BIZ_STATUS_1 = "1"; + public static final String SIGN_PATCH_BIZ_STATUS_2 = "2"; + + /** + * 公文文档上传自定义路径 + */ + public static final String UPLOAD_CUSTOM_PATH_OFFICIAL = "officialdoc"; + /** + * 公文文档下载自定义路径 + */ + public static final String DOWNLOAD_CUSTOM_PATH_OFFICIAL = "officaldown"; + + /** + * WPS存储值类别(1 code文号 2 text(WPS模板还是公文发文模板)) + */ + public static final String WPS_TYPE_1="1"; + public static final String WPS_TYPE_2="2"; + + + public final static String X_ACCESS_TOKEN = "X-Access-Token"; + public final static String X_SIGN = "X-Sign"; + public final static String X_TIMESTAMP = "X-TIMESTAMP"; + + /** + * 多租户 请求头 + */ + public final static String TENANT_ID = "tenant-id"; + + /** + * 微服务读取配置文件属性 服务地址 + */ + public final static String CLOUD_SERVER_KEY = "spring.cloud.nacos.discovery.server-addr"; + + /** + * 第三方登录 验证密码/创建用户 都需要设置一个操作码 防止被恶意调用 + */ + public final static String THIRD_LOGIN_CODE = "third_login_code"; + + /** + * 第三方APP同步方向:本地 --> 第三方APP + */ + String THIRD_SYNC_TO_APP = "SYNC_TO_APP"; + /** + * 第三方APP同步方向:第三方APP --> 本地 + */ + String THIRD_SYNC_TO_LOCAL = "SYNC_TO_LOCAL"; + + /** 系统通告消息状态:0=未发布 */ + String ANNOUNCEMENT_SEND_STATUS_0 = "0"; + /** 系统通告消息状态:1=已发布 */ + String ANNOUNCEMENT_SEND_STATUS_1 = "1"; + /** 系统通告消息状态:2=已撤销 */ + String ANNOUNCEMENT_SEND_STATUS_2 = "2"; + +} diff --git a/src/main/java/com/teaching/backend/api/CommonResult.java b/src/main/java/com/teaching/backend/api/CommonResult.java new file mode 100644 index 0000000..c333e2e --- /dev/null +++ b/src/main/java/com/teaching/backend/api/CommonResult.java @@ -0,0 +1,117 @@ +package com.teaching.backend.api; + +/** + * @auther macrozheng + * @description 通用返回对象 + * @date 2019/4/19 + * @github https://github.com/macrozheng + */ +public class CommonResult { + private long code; + private String message; + private T data; + + protected CommonResult() { + } + + protected CommonResult(long code, String message, T data) { + this.code = code; + this.message = message; + this.data = data; + } + + /** + * 成功返回结果 + * + * @param data 获取的数据 + */ + public static CommonResult success(T data) { + return new CommonResult(ResultCode.SUCCESS.getCode(), ResultCode.SUCCESS.getMessage(), data); + } + + /** + * 成功返回结果 + * + * @param data 获取的数据 + * @param message 提示信息 + */ + public static CommonResult success(T data, String message) { + return new CommonResult(ResultCode.SUCCESS.getCode(), message, data); + } + + /** + * 失败返回结果 + * @param errorCode 错误码 + */ + public static CommonResult failed(IErrorCode errorCode) { + return new CommonResult(errorCode.getCode(), errorCode.getMessage(), null); + } + + /** + * 失败返回结果 + * @param message 提示信息 + */ + public static CommonResult failed(String message) { + return new CommonResult(ResultCode.FAILED.getCode(), message, null); + } + + /** + * 失败返回结果 + */ + public static CommonResult failed() { + return failed(ResultCode.FAILED); + } + + /** + * 参数验证失败返回结果 + */ + public static CommonResult validateFailed() { + return failed(ResultCode.VALIDATE_FAILED); + } + + /** + * 参数验证失败返回结果 + * @param message 提示信息 + */ + public static CommonResult validateFailed(String message) { + return new CommonResult(ResultCode.VALIDATE_FAILED.getCode(), message, null); + } + + /** + * 未登录返回结果 + */ + public static CommonResult unauthorized(T data) { + return new CommonResult(ResultCode.UNAUTHORIZED.getCode(), ResultCode.UNAUTHORIZED.getMessage(), data); + } + + /** + * 未授权返回结果 + */ + public static CommonResult forbidden(T data) { + return new CommonResult(ResultCode.FORBIDDEN.getCode(), ResultCode.FORBIDDEN.getMessage(), data); + } + + public long getCode() { + return code; + } + + public void setCode(long code) { + this.code = code; + } + + public String getMessage() { + return message; + } + + public void setMessage(String message) { + this.message = message; + } + + public T getData() { + return data; + } + + public void setData(T data) { + this.data = data; + } +} diff --git a/src/main/java/com/teaching/backend/api/IErrorCode.java b/src/main/java/com/teaching/backend/api/IErrorCode.java new file mode 100644 index 0000000..ee536b5 --- /dev/null +++ b/src/main/java/com/teaching/backend/api/IErrorCode.java @@ -0,0 +1,13 @@ +package com.teaching.backend.api; + +/** + * @auther macrozheng + * @description 封装API的错误码 + * @date 2019/4/19 + * @github https://github.com/macrozheng + */ +public interface IErrorCode { + long getCode(); + + String getMessage(); +} diff --git a/src/main/java/com/teaching/backend/api/ResultCode.java b/src/main/java/com/teaching/backend/api/ResultCode.java new file mode 100644 index 0000000..52e4e2f --- /dev/null +++ b/src/main/java/com/teaching/backend/api/ResultCode.java @@ -0,0 +1,30 @@ +package com.teaching.backend.api; + +/** + * @auther macrozheng + * @description 枚举了一些常用API操作码 + * @date 2019/4/19 + * @github https://github.com/macrozheng + */ +public enum ResultCode implements IErrorCode { + SUCCESS(200, "操作成功"), + FAILED(500, "操作失败"), + VALIDATE_FAILED(404, "参数检验失败"), + UNAUTHORIZED(401, "暂未登录或token已经过期"), + FORBIDDEN(403, "没有相关权限"); + private long code; + private String message; + + private ResultCode(long code, String message) { + this.code = code; + this.message = message; + } + + public long getCode() { + return code; + } + + public String getMessage() { + return message; + } +} diff --git a/src/main/java/com/teaching/backend/component/DynamicAccessDecisionManager.java b/src/main/java/com/teaching/backend/component/DynamicAccessDecisionManager.java new file mode 100644 index 0000000..6e64e49 --- /dev/null +++ b/src/main/java/com/teaching/backend/component/DynamicAccessDecisionManager.java @@ -0,0 +1,51 @@ +package com.teaching.backend.component; + +import cn.hutool.core.collection.CollUtil; +import org.springframework.security.access.AccessDecisionManager; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.authentication.InsufficientAuthenticationException; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.GrantedAuthority; + +import java.util.Collection; +import java.util.Iterator; + +/** + * 动态权限决策管理器,用于判断用户是否有访问权限 + * Created by macro on 2020/2/7. + */ +public class DynamicAccessDecisionManager implements AccessDecisionManager { + + @Override + public void decide(Authentication authentication, Object object, + Collection configAttributes) throws AccessDeniedException, InsufficientAuthenticationException { + // 当接口未被配置资源时直接放行 + if (CollUtil.isEmpty(configAttributes)) { + return; + } + Iterator iterator = configAttributes.iterator(); + while (iterator.hasNext()) { + ConfigAttribute configAttribute = iterator.next(); + //将访问所需资源或用户拥有资源进行比对 + String needAuthority = configAttribute.getAttribute(); + for (GrantedAuthority grantedAuthority : authentication.getAuthorities()) { + if (needAuthority.trim().equals(grantedAuthority.getAuthority())) { + return; + } + } + } + throw new AccessDeniedException("抱歉,您没有访问权限"); + } + + @Override + public boolean supports(ConfigAttribute configAttribute) { + return true; + } + + @Override + public boolean supports(Class aClass) { + return true; + } + +} diff --git a/src/main/java/com/teaching/backend/component/DynamicSecurityFilter.java b/src/main/java/com/teaching/backend/component/DynamicSecurityFilter.java new file mode 100644 index 0000000..b405873 --- /dev/null +++ b/src/main/java/com/teaching/backend/component/DynamicSecurityFilter.java @@ -0,0 +1,77 @@ +package com.teaching.backend.component; + +import com.teaching.backend.config.IgnoreUrlsConfig; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpMethod; +import org.springframework.security.access.SecurityMetadataSource; +import org.springframework.security.access.intercept.AbstractSecurityInterceptor; +import org.springframework.security.access.intercept.InterceptorStatusToken; +import org.springframework.security.web.FilterInvocation; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; + +import javax.servlet.*; +import javax.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * 动态权限过滤器,用于实现基于路径的动态权限过滤 + * Created by macro on 2020/2/7. + */ +public class DynamicSecurityFilter extends AbstractSecurityInterceptor implements Filter { + + @Autowired + private DynamicSecurityMetadataSource dynamicSecurityMetadataSource; + @Autowired + private IgnoreUrlsConfig ignoreUrlsConfig; + + @Autowired + public void setMyAccessDecisionManager(DynamicAccessDecisionManager dynamicAccessDecisionManager) { + super.setAccessDecisionManager(dynamicAccessDecisionManager); + } + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + HttpServletRequest request = (HttpServletRequest) servletRequest; + FilterInvocation fi = new FilterInvocation(servletRequest, servletResponse, filterChain); + //OPTIONS请求直接放行 + if(request.getMethod().equals(HttpMethod.OPTIONS.toString())){ + fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); + return; + } + //白名单请求直接放行 + PathMatcher pathMatcher = new AntPathMatcher(); + for (String path : ignoreUrlsConfig.getUrls()) { + if(pathMatcher.match(path,request.getRequestURI())){ + fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); + return; + } + } + //此处会调用AccessDecisionManager中的decide方法进行鉴权操作 + InterceptorStatusToken token = super.beforeInvocation(fi); + try { + fi.getChain().doFilter(fi.getRequest(), fi.getResponse()); + } finally { + super.afterInvocation(token, null); + } + } + + @Override + public void destroy() { + } + + @Override + public Class getSecureObjectClass() { + return FilterInvocation.class; + } + + @Override + public SecurityMetadataSource obtainSecurityMetadataSource() { + return dynamicSecurityMetadataSource; + } + +} diff --git a/src/main/java/com/teaching/backend/component/DynamicSecurityMetadataSource.java b/src/main/java/com/teaching/backend/component/DynamicSecurityMetadataSource.java new file mode 100644 index 0000000..511f47d --- /dev/null +++ b/src/main/java/com/teaching/backend/component/DynamicSecurityMetadataSource.java @@ -0,0 +1,64 @@ +package com.teaching.backend.component; + +import cn.hutool.core.util.URLUtil; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.web.FilterInvocation; +import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; +import org.springframework.util.AntPathMatcher; +import org.springframework.util.PathMatcher; + +import javax.annotation.PostConstruct; +import java.util.*; + +/** + * 动态权限数据源,用于获取动态权限规则 + * Created by macro on 2020/2/7. + */ +public class DynamicSecurityMetadataSource implements FilterInvocationSecurityMetadataSource { + + private static Map configAttributeMap = null; + @Autowired + private DynamicSecurityService dynamicSecurityService; + + @PostConstruct + public void loadDataSource() { + configAttributeMap = dynamicSecurityService.loadDataSource(); + } + + public void clearDataSource() { + configAttributeMap.clear(); + configAttributeMap = null; + } + + @Override + public Collection getAttributes(Object o) throws IllegalArgumentException { + if (configAttributeMap == null) this.loadDataSource(); + List configAttributes = new ArrayList<>(); + //获取当前访问的路径 + String url = ((FilterInvocation) o).getRequestUrl(); + String path = URLUtil.getPath(url); + PathMatcher pathMatcher = new AntPathMatcher(); + Iterator iterator = configAttributeMap.keySet().iterator(); + //获取访问该路径所需资源 + while (iterator.hasNext()) { + String pattern = iterator.next(); + if (pathMatcher.match(pattern, path)) { + configAttributes.add(configAttributeMap.get(pattern)); + } + } + // 未设置操作请求权限,返回空集合 + return configAttributes; + } + + @Override + public Collection getAllConfigAttributes() { + return null; + } + + @Override + public boolean supports(Class aClass) { + return true; + } + +} diff --git a/src/main/java/com/teaching/backend/component/DynamicSecurityService.java b/src/main/java/com/teaching/backend/component/DynamicSecurityService.java new file mode 100644 index 0000000..1ef65d3 --- /dev/null +++ b/src/main/java/com/teaching/backend/component/DynamicSecurityService.java @@ -0,0 +1,16 @@ +package com.teaching.backend.component; + +import org.springframework.security.access.ConfigAttribute; + +import java.util.Map; + +/** + * 动态权限相关业务接口 + * Created by macro on 2020/2/7. + */ +public interface DynamicSecurityService { + /** + * 加载资源ANT通配符和资源对应MAP + */ + Map loadDataSource(); +} diff --git a/src/main/java/com/teaching/backend/component/JwtAuthenticationTokenFilter.java b/src/main/java/com/teaching/backend/component/JwtAuthenticationTokenFilter.java new file mode 100644 index 0000000..6ee681e --- /dev/null +++ b/src/main/java/com/teaching/backend/component/JwtAuthenticationTokenFilter.java @@ -0,0 +1,58 @@ +package com.teaching.backend.component; + + +import com.teaching.backend.utils.JwtTokenUtil; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.web.authentication.WebAuthenticationDetailsSource; +import org.springframework.web.filter.OncePerRequestFilter; + +import javax.servlet.FilterChain; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * JWT登录授权过滤器 + * Created by macro on 2018/4/26. + */ +public class JwtAuthenticationTokenFilter extends OncePerRequestFilter { + private static final Logger LOGGER = LoggerFactory.getLogger(JwtAuthenticationTokenFilter.class); + @Autowired + private UserDetailsService userDetailsService; + @Autowired + private JwtTokenUtil jwtTokenUtil; + @Value("${jwt.tokenHeader}") + private String tokenHeader; + @Value("${jwt.tokenHead}") + private String tokenHead; + + @Override + protected void doFilterInternal(HttpServletRequest request, + HttpServletResponse response, + FilterChain chain) throws ServletException, IOException { + String authHeader = request.getHeader(this.tokenHeader); + if (authHeader != null && authHeader.startsWith(this.tokenHead)) { + String authToken = authHeader.substring(this.tokenHead.length());// The part after "Bearer " + String username = jwtTokenUtil.getUserNameFromToken(authToken); + LOGGER.info("checking username:{}", username); + if (username != null && SecurityContextHolder.getContext().getAuthentication() == null) { + UserDetails userDetails = this.userDetailsService.loadUserByUsername(username); + if (jwtTokenUtil.validateToken(authToken, userDetails)) { + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request)); + LOGGER.info("authenticated user:{}", username); + SecurityContextHolder.getContext().setAuthentication(authentication); + } + } + } + chain.doFilter(request, response); + } +} diff --git a/src/main/java/com/teaching/backend/component/RestAuthenticationEntryPoint.java b/src/main/java/com/teaching/backend/component/RestAuthenticationEntryPoint.java new file mode 100644 index 0000000..ee42916 --- /dev/null +++ b/src/main/java/com/teaching/backend/component/RestAuthenticationEntryPoint.java @@ -0,0 +1,27 @@ +package com.teaching.backend.component; + +import cn.hutool.json.JSONUtil; +import com.teaching.backend.api.CommonResult; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.web.AuthenticationEntryPoint; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 自定义未登录或者token失效时的返回结果 + * Created by macro on 2018/5/14. + */ +public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint { + @Override + public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Cache-Control","no-cache"); + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json"); + response.getWriter().println(JSONUtil.parse(CommonResult.unauthorized(authException.getMessage()))); + response.getWriter().flush(); + } +} diff --git a/src/main/java/com/teaching/backend/component/RestfulAccessDeniedHandler.java b/src/main/java/com/teaching/backend/component/RestfulAccessDeniedHandler.java new file mode 100644 index 0000000..ffddd0b --- /dev/null +++ b/src/main/java/com/teaching/backend/component/RestfulAccessDeniedHandler.java @@ -0,0 +1,29 @@ +package com.teaching.backend.component; + +import cn.hutool.json.JSONUtil; +import com.teaching.backend.api.CommonResult; +import org.springframework.security.access.AccessDeniedException; +import org.springframework.security.web.access.AccessDeniedHandler; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; + +/** + * 自定义无权限访问的返回结果 + * Created by macro on 2018/4/26. + */ +public class RestfulAccessDeniedHandler implements AccessDeniedHandler{ + @Override + public void handle(HttpServletRequest request, + HttpServletResponse response, + AccessDeniedException e) throws IOException, ServletException { + response.setHeader("Access-Control-Allow-Origin", "*"); + response.setHeader("Cache-Control","no-cache"); + response.setCharacterEncoding("UTF-8"); + response.setContentType("application/json"); + response.getWriter().println(JSONUtil.parse(CommonResult.forbidden(e.getMessage()))); + response.getWriter().flush(); + } +} diff --git a/src/main/java/com/teaching/backend/config/CommonSecurityConfig.java b/src/main/java/com/teaching/backend/config/CommonSecurityConfig.java new file mode 100644 index 0000000..5a93551 --- /dev/null +++ b/src/main/java/com/teaching/backend/config/CommonSecurityConfig.java @@ -0,0 +1,67 @@ +package com.teaching.backend.config; + + +import com.teaching.backend.component.*; +import com.teaching.backend.utils.JwtTokenUtil; +import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; + +/** + * SpringSecurity通用配置 + * 包括通用Bean、Security通用Bean及动态权限通用Bean + * Created by macro on 2022/5/20. + */ +@Configuration +public class CommonSecurityConfig { + + @Bean + public PasswordEncoder passwordEncoder() { + return new BCryptPasswordEncoder(); + } + + @Bean + public IgnoreUrlsConfig ignoreUrlsConfig() { + return new IgnoreUrlsConfig(); + } + + @Bean + public JwtTokenUtil jwtTokenUtil() { + return new JwtTokenUtil(); + } + + @Bean + public RestfulAccessDeniedHandler restfulAccessDeniedHandler() { + return new RestfulAccessDeniedHandler(); + } + + @Bean + public RestAuthenticationEntryPoint restAuthenticationEntryPoint() { + return new RestAuthenticationEntryPoint(); + } + + @Bean + public JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter(){ + return new JwtAuthenticationTokenFilter(); + } + + @ConditionalOnBean(name = "dynamicSecurityService") + @Bean + public DynamicAccessDecisionManager dynamicAccessDecisionManager() { + return new DynamicAccessDecisionManager(); + } + + @ConditionalOnBean(name = "dynamicSecurityService") + @Bean + public DynamicSecurityMetadataSource dynamicSecurityMetadataSource() { + return new DynamicSecurityMetadataSource(); + } + + @ConditionalOnBean(name = "dynamicSecurityService") + @Bean + public DynamicSecurityFilter dynamicSecurityFilter(){ + return new DynamicSecurityFilter(); + } +} diff --git a/src/main/java/com/teaching/backend/config/IgnoreUrlsConfig.java b/src/main/java/com/teaching/backend/config/IgnoreUrlsConfig.java new file mode 100644 index 0000000..bd79c19 --- /dev/null +++ b/src/main/java/com/teaching/backend/config/IgnoreUrlsConfig.java @@ -0,0 +1,20 @@ +package com.teaching.backend.config; + +import lombok.Getter; +import lombok.Setter; +import org.springframework.boot.context.properties.ConfigurationProperties; +import java.util.ArrayList; +import java.util.List; + +/** + * SpringSecurity白名单资源路径配置 + * Created by macro on 2018/11/5. + */ +@Getter +@Setter +@ConfigurationProperties(prefix = "secure.ignored") +public class IgnoreUrlsConfig { + + private List urls = new ArrayList<>(); + +} diff --git a/src/main/java/com/teaching/backend/config/MallSecurityConfig.java b/src/main/java/com/teaching/backend/config/MallSecurityConfig.java new file mode 100644 index 0000000..93060ca --- /dev/null +++ b/src/main/java/com/teaching/backend/config/MallSecurityConfig.java @@ -0,0 +1,47 @@ +package com.teaching.backend.config; + + +import com.teaching.backend.service.umsAdmin.UmsAdminService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.access.ConfigAttribute; +import org.springframework.security.core.userdetails.UserDetailsService; + +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; + +/** + * mall-security模块相关配置 + * Created by macro on 2019/11/9. + */ +@Configuration +public class MallSecurityConfig { + + @Autowired + private UmsAdminService umsadminService; +// @Autowired +// private UmsResourceService resourceService; + + @Bean + public UserDetailsService userDetailsService() { + //获取登录用户信息 + return username -> umsadminService.loadUserByUsername(username); + } + +// @Bean +// public DynamicSecurityService dynamicSecurityService() { +// return new DynamicSecurityService() { +// @Override +// public Map loadDataSource() { +// Map map = new ConcurrentHashMap<>(); +// List resourceList = resourceService.listAll(); +// for (UmsResource resource : resourceList) { +// map.put(resource.getUrl(), new org.springframework.security.access.SecurityConfig(resource.getId() + ":" + resource.getName())); +// } +// return map; +// } +// }; +// } +} diff --git a/src/main/java/com/teaching/backend/config/SecurityConfig.java b/src/main/java/com/teaching/backend/config/SecurityConfig.java new file mode 100644 index 0000000..6e5b527 --- /dev/null +++ b/src/main/java/com/teaching/backend/config/SecurityConfig.java @@ -0,0 +1,75 @@ +package com.teaching.backend.config; + +import com.teaching.backend.component.*; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.HttpMethod; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configurers.ExpressionUrlAuthorizationConfigurer; +import org.springframework.security.config.http.SessionCreationPolicy; +import org.springframework.security.web.SecurityFilterChain; +import org.springframework.security.web.access.intercept.FilterSecurityInterceptor; +import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; + + +/** + * SpringSecurity相关配置,仅用于配置SecurityFilterChain + * Created by macro on 2019/11/5. + */ +@Configuration +@EnableWebSecurity +public class SecurityConfig { + + @Autowired + private IgnoreUrlsConfig ignoreUrlsConfig; + @Autowired + private RestfulAccessDeniedHandler restfulAccessDeniedHandler; + @Autowired + private RestAuthenticationEntryPoint restAuthenticationEntryPoint; + @Autowired + private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter; + @Autowired(required = false) + private DynamicSecurityService dynamicSecurityService; + @Autowired(required = false) + private DynamicSecurityFilter dynamicSecurityFilter; + + @Bean + SecurityFilterChain filterChain(HttpSecurity httpSecurity) throws Exception { + ExpressionUrlAuthorizationConfigurer.ExpressionInterceptUrlRegistry registry = httpSecurity + .authorizeRequests(); + //不需要保护的资源路径允许访问 + for (String url : ignoreUrlsConfig.getUrls()) { + registry.antMatchers(url).permitAll(); + } + //允许跨域请求的OPTIONS请求 + registry.antMatchers(HttpMethod.OPTIONS) + .permitAll(); + // 任何请求需要身份认证 + registry.and() + .authorizeRequests() + .anyRequest() + .authenticated() + // 关闭跨站请求防护及不使用session + .and() + .csrf() + .disable() + .sessionManagement() + .sessionCreationPolicy(SessionCreationPolicy.STATELESS) + // 自定义权限拒绝处理类 + .and() + .exceptionHandling() + .accessDeniedHandler(restfulAccessDeniedHandler) + .authenticationEntryPoint(restAuthenticationEntryPoint) + // 自定义权限拦截器JWT过滤器 + .and() + .addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class); + //有动态权限配置时添加动态权限校验过滤器 + if(dynamicSecurityService!=null){ + registry.and().addFilterBefore(dynamicSecurityFilter, FilterSecurityInterceptor.class); + } + return httpSecurity.build(); + } + +} diff --git a/src/main/java/com/teaching/backend/constant/RegexPatterns.java b/src/main/java/com/teaching/backend/constant/RegexPatterns.java new file mode 100644 index 0000000..dcfc8bb --- /dev/null +++ b/src/main/java/com/teaching/backend/constant/RegexPatterns.java @@ -0,0 +1,17 @@ +package com.teaching.backend.constant; + + +public abstract class RegexPatterns { + /** + * 手机号正则 + */ + public static final String PHONE_REGEX = "^1([38][0-9]|4[579]|5[0-3,5-9]|6[6]|7[0135678]|9[89])\\d{8}$"; + /** + * 密码正则。4~32位的字母、数字、下划线 + */ + public static final String PASSWORD_REGEX = "^\\w{4,32}$"; + /** + * 验证码正则, 6位数字或字母 + */ + public static final String VERIFY_CODE_REGEX = "^[a-zA-Z\\d]{6}$"; +} diff --git a/src/main/java/com/teaching/backend/constant/test1.java b/src/main/java/com/teaching/backend/constant/test1.java deleted file mode 100644 index b42d1ee..0000000 --- a/src/main/java/com/teaching/backend/constant/test1.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.teaching.backend.constant; - -/** - * @Author:youhang - * @Date:2024-05-30-18:20 - * @Description: - */ -public class test1 { -} diff --git a/src/main/java/com/teaching/backend/controller/records/LearningRecordsController.java b/src/main/java/com/teaching/backend/controller/records/LearningRecordsController.java index 81544ea..20aaed3 100644 --- a/src/main/java/com/teaching/backend/controller/records/LearningRecordsController.java +++ b/src/main/java/com/teaching/backend/controller/records/LearningRecordsController.java @@ -36,7 +36,7 @@ // @RequestParam(value = "pagenum", defaultValue = "1") int pagenum, // @RequestParam(value = "pagesize", defaultValue = "15") int pagesize, // @RequestParam String userId){ -// PageHelper.startPage(pagenum,pagesize,"id desc"); +// PageHelper.startPage(pagenum,pagesize); // List cs= learningRecordsService.getAll(userId); // List pageCs = new ArrayList<>(); // //当前页面 @@ -48,12 +48,12 @@ // System.out.println("当前页面大小:"+pagesize); // System.out.println("当前页面内容:"+pageCs); //// PageInfo pageInfo = new PageInfo<>(cs); -// pageInfo.setPageSize(pagesize);//设置当前页面大小 -// pageInfo.setPageNum(pagenum);//设置当前页码 -// pageInfo.setSize(pagesize);//不知道是啥,--------- -// pageInfo.setTotal(cs.size());//设置总条数 +//// pageInfo.setPageSize(pagesize);//设置当前页面大小 +//// pageInfo.setPageNum(pagenum);//设置当前页码 +//// pageInfo.setSize(pagesize);//不知道是啥,--------- +//// pageInfo.setTotal(cs.size());//设置总条数 // long total = pageInfo.getTotal(); // 总记录数 -// pageInfo.setPages((int)(Math.ceil((double) total / pagesize)));//设置总页数 +//// pageInfo.setPages((int)(Math.ceil((double) total / pagesize)));//设置总页数 // return ResultUtils.success(pageInfo); // } // diff --git a/src/main/java/com/teaching/backend/controller/umsAdmin/UmsAdminController.java b/src/main/java/com/teaching/backend/controller/umsAdmin/UmsAdminController.java new file mode 100644 index 0000000..4983f03 --- /dev/null +++ b/src/main/java/com/teaching/backend/controller/umsAdmin/UmsAdminController.java @@ -0,0 +1,155 @@ +package com.teaching.backend.controller.umsAdmin; + +import cn.hutool.core.collection.CollUtil; +import com.teaching.backend.api.CommonResult; +import com.teaching.backend.model.dto.UmsAdminParam; +import com.teaching.backend.model.dto.UpdateAdminPasswordParam; +import com.teaching.backend.model.entity.umsAdmin.UmsAdmin; +import com.teaching.backend.model.entity.umsAdmin.UmsRole; +import com.teaching.backend.service.umsAdmin.UmsAdminService; +import com.teaching.backend.service.umsAdmin.UmsRoleService; +import io.swagger.annotations.Api; +import io.swagger.annotations.ApiOperation; +import lombok.extern.slf4j.Slf4j; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.ResponseEntity; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; +import javax.servlet.http.HttpServletRequest; +import java.security.Principal; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + + +/** + * @Author:xhn + * @Date:2024-05-30-18:15 + * @Description:login + */ +@RestController +@Api(tags = "UmsAdminController") +@RequestMapping("/user") +@Slf4j +public class UmsAdminController { + @Value("${jwt.tokenHeader}") + private String tokenHeader; + @Value("${jwt.tokenHead}") + private String tokenHead; + @Autowired + private UmsAdminService umsAdminService; + @Autowired + private UmsRoleService umsRoleService; + + + @ApiOperation(value = "用户注册") + @PostMapping("/register") + public CommonResult register(@Validated @RequestBody UmsAdminParam umsAdminParam) { + if (umsAdminParam == null) { + return CommonResult.failed(); + } + UmsAdmin umsAdmin = umsAdminService.register(umsAdminParam); + return CommonResult.success(umsAdmin); + } + + @ApiOperation(value = "登录以后返回token") + @PostMapping("/login") + public CommonResult login(@Validated @RequestBody UmsAdmin umsAdmin) { + String token = umsAdminService.login(umsAdmin.getUsername(), umsAdmin.getPassword()); + if (token == null) { + return CommonResult.validateFailed("用户名或密码错误"); + } + Map tokenMap = new HashMap<>(); + tokenMap.put("token", token); + tokenMap.put("tokenHead", tokenHead); + return CommonResult.success(tokenMap); + } + + /** + * 发送短信 + * @param phone + * @return + */ + @ApiOperation(value = "发送短信返回验证码") + @PostMapping("/code") + public CommonResult sendVerifyCode(@RequestParam("phone")String phone){ + return CommonResult.success(umsAdminService.sendVerifyCode(phone)); + } + + @ApiOperation(value = "手机号注册") + @PostMapping("/phone/register") + public CommonResult phoneRegister(@Validated @RequestBody UmsAdminParam umsAdminParam) { + if (umsAdminParam == null) { + return CommonResult.failed(); + } + UmsAdmin umsAdmin = umsAdminService.phoneRegister(umsAdminParam); + return CommonResult.success(umsAdmin); + } + + @ApiOperation(value = "刷新token") + @GetMapping("/refreshToken") + public CommonResult refreshToken(HttpServletRequest request) { + String token = request.getHeader(tokenHeader); + String refreshToken = umsAdminService.refreshToken(token); + if (refreshToken == null) { + return CommonResult.failed("token已经过期!"); + } + Map tokenMap = new HashMap<>(); + tokenMap.put("token", refreshToken); + tokenMap.put("tokenHead", tokenHead); + return CommonResult.success(tokenMap); + } + + @ApiOperation(value = "获取当前登录用户信息") + @GetMapping ("/info") + public CommonResult getAdminInfo(Principal principal) { + if(principal == null){ + return CommonResult.unauthorized(null); + } + String username = principal.getName(); + UmsAdmin umsAdmin = umsAdminService.getAdminByUsername(username); + Map data = new HashMap<>(); + data.put("id",umsAdmin.getId()); + data.put("username", umsAdmin.getUsername()); + data.put("menus", umsRoleService.getMenuList(umsAdmin.getId())); + data.put("phone", umsAdmin.getPhone()); + data.put("nickName", umsAdmin.getNickName()); + data.put("icon", umsAdmin.getIcon()); + List roleList = umsAdminService.getRoleList(umsAdmin.getId()); + if(CollUtil.isNotEmpty(roleList)){ + List roles = roleList.stream().map(UmsRole::getName).collect(Collectors.toList()); + data.put("roles",roles); + } + return CommonResult.success(data); + } + + @ApiOperation("修改指定用户信息") + @PostMapping("/update") + public CommonResult updateUms(@RequestBody UmsAdmin umsadmin) { + boolean count = umsAdminService.updateUms(umsadmin); + if (count == true) { + return CommonResult.success(count); + } + return CommonResult.failed(); + } + + @ApiOperation("修改指定用户密码") + @PostMapping("/updatePassword") + public CommonResult updatePassword(@Validated @RequestBody UpdateAdminPasswordParam updatePasswordParam) { + int status = umsAdminService.updatePassword(updatePasswordParam); + if (status > 0) { + return CommonResult.success(status); + } else if (status == -1) { + return CommonResult.failed("提交参数不合法"); + } else if (status == -2) { + return CommonResult.failed("找不到该用户"); + } else if (status == -3) { + return CommonResult.failed("旧密码错误"); + } else { + return CommonResult.failed(); + } + } + +} diff --git a/src/main/java/com/teaching/backend/exception/ApiException.java b/src/main/java/com/teaching/backend/exception/ApiException.java new file mode 100644 index 0000000..460ba4d --- /dev/null +++ b/src/main/java/com/teaching/backend/exception/ApiException.java @@ -0,0 +1,33 @@ +package com.teaching.backend.exception; + + +import com.teaching.backend.api.IErrorCode; + +/** + * 自定义API异常 + * Created by macro on 2020/2/27. + */ +public class ApiException extends RuntimeException { + private IErrorCode errorCode; + + public ApiException(IErrorCode errorCode) { + super(errorCode.getMessage()); + this.errorCode = errorCode; + } + + public ApiException(String message) { + super(message); + } + + public ApiException(Throwable cause) { + super(cause); + } + + public ApiException(String message, Throwable cause) { + super(message, cause); + } + + public IErrorCode getErrorCode() { + return errorCode; + } +} diff --git a/src/main/java/com/teaching/backend/exception/Asserts.java b/src/main/java/com/teaching/backend/exception/Asserts.java new file mode 100644 index 0000000..0866235 --- /dev/null +++ b/src/main/java/com/teaching/backend/exception/Asserts.java @@ -0,0 +1,18 @@ +package com.teaching.backend.exception; + + +import com.teaching.backend.api.IErrorCode; + +/** + * 断言处理类,用于抛出各种API异常 + * Created by macro on 2020/2/27. + */ +public class Asserts { + public static void fail(String message) { + throw new ApiException(message); + } + + public static void fail(IErrorCode errorCode) { + throw new ApiException(errorCode); + } +} diff --git a/src/main/java/com/teaching/backend/exception/LyException.java b/src/main/java/com/teaching/backend/exception/LyException.java new file mode 100644 index 0000000..e544d72 --- /dev/null +++ b/src/main/java/com/teaching/backend/exception/LyException.java @@ -0,0 +1,31 @@ +package com.teaching.backend.exception; + +import lombok.Getter; + + +@Getter +public class LyException extends RuntimeException { + /** + * 异常状态码信息 + */ + private int status; + + public LyException(int status) { + this.status = status; + } + + public LyException(int status, String message) { + super(message); + this.status = status; + } + + public LyException(int status, String message, Throwable cause) { + super(message, cause); + this.status = status; + } + + public LyException(int status, Throwable cause) { + super(cause); + this.status = status; + } +} diff --git a/src/main/java/com/teaching/backend/manager/test1.java b/src/main/java/com/teaching/backend/manager/test1.java deleted file mode 100644 index 7c28195..0000000 --- a/src/main/java/com/teaching/backend/manager/test1.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.teaching.backend.manager; - -/** - * @Author:youhang - * @Date:2024-05-30-18:20 - * @Description: - */ -public class test1 { -} diff --git a/src/main/java/com/teaching/backend/mapper/umsAdmin/UmsAdminMapper.java b/src/main/java/com/teaching/backend/mapper/umsAdmin/UmsAdminMapper.java new file mode 100644 index 0000000..af4498b --- /dev/null +++ b/src/main/java/com/teaching/backend/mapper/umsAdmin/UmsAdminMapper.java @@ -0,0 +1,9 @@ +package com.teaching.backend.mapper.umsAdmin; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.teaching.backend.model.entity.umsAdmin.UmsAdmin; +import org.apache.ibatis.annotations.Mapper; + +@Mapper +public interface UmsAdminMapper extends BaseMapper { +} diff --git a/src/main/java/com/teaching/backend/mapper/umsAdmin/UmsAdminRoleRelationMapper.java b/src/main/java/com/teaching/backend/mapper/umsAdmin/UmsAdminRoleRelationMapper.java new file mode 100644 index 0000000..402bcbf --- /dev/null +++ b/src/main/java/com/teaching/backend/mapper/umsAdmin/UmsAdminRoleRelationMapper.java @@ -0,0 +1,38 @@ +package com.teaching.backend.mapper.umsAdmin; + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.teaching.backend.model.entity.umsAdmin.UmsAdminRoleRelation; +import com.teaching.backend.model.entity.umsAdmin.UmsResource; +import com.teaching.backend.model.entity.umsAdmin.UmsRole; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 后台用户与角色关系管理自定义Dao + * Created by macro on 2018/10/8. + */ +@Mapper +public interface UmsAdminRoleRelationMapper extends BaseMapper { +// /** +// * 批量插入用户角色关系 +// */ +// int insertList(@Param("list") List adminRoleRelationList); + + /** + * 获取用于所有角色 + */ + List getRoleList(@Param("adminId") Long adminId); + + /** + * 获取用户所有可访问资源 + */ + List getResourceList(@Param("adminId") Long adminId); + + +// /** +// * 获取资源相关用户ID列表 +// */ +// List getAdminIdList(@Param("resourceId") Long resourceId); +} diff --git a/src/main/java/com/teaching/backend/mapper/umsAdmin/UmsRoleMapper.java b/src/main/java/com/teaching/backend/mapper/umsAdmin/UmsRoleMapper.java new file mode 100644 index 0000000..f702a8f --- /dev/null +++ b/src/main/java/com/teaching/backend/mapper/umsAdmin/UmsRoleMapper.java @@ -0,0 +1,31 @@ +package com.teaching.backend.mapper.umsAdmin; + + +import com.baomidou.mybatisplus.core.mapper.BaseMapper; +import com.teaching.backend.model.entity.umsAdmin.UmsAdminRoleRelation; +import com.teaching.backend.model.entity.umsAdmin.UmsMenu; +import com.teaching.backend.model.entity.umsAdmin.UmsRole; +import org.apache.ibatis.annotations.Mapper; +import org.apache.ibatis.annotations.Param; + +import java.util.List; + +/** + * 后台角色管理自定义Dao + * Created by macro on 2020/2/2. + */ +@Mapper +public interface UmsRoleMapper extends BaseMapper { + /** + * 根据后台用户ID获取菜单 + */ + List getMenuList(@Param("adminId") Long adminId); +// /** +// * 根据角色ID获取菜单 +// */ +// List getMenuListByRoleId(@Param("roleId") Long roleId); +// /** +// * 根据角色ID获取资源 +// */ +// List getResourceListByRoleId(@Param("roleId") Long roleId); +} diff --git a/src/main/java/com/teaching/backend/model/dto/UmsAdminParam.java b/src/main/java/com/teaching/backend/model/dto/UmsAdminParam.java new file mode 100644 index 0000000..8bdac88 --- /dev/null +++ b/src/main/java/com/teaching/backend/model/dto/UmsAdminParam.java @@ -0,0 +1,30 @@ +package com.teaching.backend.model.dto; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@TableName("ums_admin") +public class UmsAdminParam implements Serializable { + + //用户名 + private String username; + + //密码 + private String password; + + //手机号 + private String phone; + + //昵称 + private String nickName; + + //头像 + private String icon; + +} diff --git a/src/main/java/com/teaching/backend/model/dto/UpdateAdminPasswordParam.java b/src/main/java/com/teaching/backend/model/dto/UpdateAdminPasswordParam.java new file mode 100644 index 0000000..b7add78 --- /dev/null +++ b/src/main/java/com/teaching/backend/model/dto/UpdateAdminPasswordParam.java @@ -0,0 +1,22 @@ +package com.teaching.backend.model.dto; + +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + + +/** + * 修改用户名密码参数 + * Created by macro on 2019/10/9. + */ +@Data +public class UpdateAdminPasswordParam { +// @NotEmpty + @ApiModelProperty(value = "用户名", required = true) + private String username; +// @NotEmpty + @ApiModelProperty(value = "旧密码", required = true) + private String oldPassword; +// @NotEmpty + @ApiModelProperty(value = "新密码", required = true) + private String newPassword; +} diff --git a/src/main/java/com/teaching/backend/model/entity/records/LearningRecords.java b/src/main/java/com/teaching/backend/model/entity/records/LearningRecords.java index be7d920..37cd5ef 100644 --- a/src/main/java/com/teaching/backend/model/entity/records/LearningRecords.java +++ b/src/main/java/com/teaching/backend/model/entity/records/LearningRecords.java @@ -1,96 +1,96 @@ -package com.teaching.backend.model.entity.records; - - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import com.baomidou.mybatisplus.annotation.TableName; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - -import java.time.LocalDateTime; - - -@Data -@EqualsAndHashCode(callSuper = false) -@Accessors(chain = true) -@TableName("learning_records") -public class LearningRecords { - private static final long serialVersionUID = 1L; - - /** - * 内部编号 - */ - @TableId(value = "id", type = IdType.ASSIGN_ID) - private String id; - - /** - * 用户id - */ - private String userId; - - /** - * 课程id - */ - private String coursesId; - /** - * 章节id - */ - private String chapterId; - /** - * 知识点id - */ - private String knowledgePointId; - /** - * 资源id - */ - private String resourceId; - /** - * 访问时间 - */ - private LocalDateTime accessTime; - - /** - * 学习方式:打开; 1,打开过,2未打开 - */ - private String learningMethod1; - /** - * 学习方式:下载; 1下载过, 2未下载 - */ - private String learningMethod2; - /** - *视频学习时长 - */ - private String videoDuration; - - /** - *是否完成观看:1,已完成,0未完成 - */ - private String isCompleted; - - /** - * 记录封面图片 - */ - private String content; - /** - * 资源地址 - */ - private String address; - - /** - * 是否存在: 1存在;0不存在; - */ - private String status; - /** - * 类型, 如:1,课程; 2,章节; 3,知识点; 4,学习资源 - */ - private String type; - /** - * 父节点 - */ - private String parentNode; - - - - -} +//package com.teaching.backend.model.entity.records; +// +// +//import com.baomidou.mybatisplus.annotation.IdType; +//import com.baomidou.mybatisplus.annotation.TableId; +//import com.baomidou.mybatisplus.annotation.TableName; +//import lombok.Data; +//import lombok.EqualsAndHashCode; +//import lombok.experimental.Accessors; +// +//import java.time.LocalDateTime; +// +// +//@Data +//@EqualsAndHashCode(callSuper = false) +//@Accessors(chain = true) +//@TableName("learning_records") +//public class LearningRecords { +// private static final long serialVersionUID = 1L; +// +// /** +// * 内部编号 +// */ +// @TableId(value = "id", type = IdType.ASSIGN_ID) +// private String id; +// +// /** +// * 用户id +// */ +// private String userId; +// +// /** +// * 课程id +// */ +// private String coursesId; +// /** +// * 章节id +// */ +// private String chapterId; +// /** +// * 知识点id +// */ +// private String knowledgePointId; +// /** +// * 资源id +// */ +// private String resourceId; +// /** +// * 访问时间 +// */ +// private LocalDateTime accessTime; +// +// /** +// * 学习方式:打开; 1,打开过,2未打开 +// */ +// private String learningMethod1; +// /** +// * 学习方式:下载; 1下载过, 2未下载 +// */ +// private String learningMethod2; +// /** +// *视频学习时长 +// */ +// private String videoDuration; +// +// /** +// *是否完成观看:1,已完成,0未完成 +// */ +// private String isCompleted; +// +// /** +// * 记录封面图片 +// */ +// private String content; +// /** +// * 资源地址 +// */ +// private String address; +// +// /** +// * 是否存在: 1存在;0不存在; +// */ +// private String status; +// /** +// * 类型, 如:1,课程; 2,章节; 3,知识点; 4,学习资源 +// */ +// private String type; +// /** +// * 父节点 +// */ +// private String parentNode; +// +// +// +// +//} diff --git a/src/main/java/com/teaching/backend/model/entity/umsAdmin/AdminUserDetails.java b/src/main/java/com/teaching/backend/model/entity/umsAdmin/AdminUserDetails.java new file mode 100644 index 0000000..757fd4b --- /dev/null +++ b/src/main/java/com/teaching/backend/model/entity/umsAdmin/AdminUserDetails.java @@ -0,0 +1,64 @@ +package com.teaching.backend.model.entity.umsAdmin; + +import lombok.Data; +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +/** + * SpringSecurity需要的用户信息封装类 + * Created by macro on 2018/4/26. + */ +public class AdminUserDetails implements UserDetails { + //后台用户 + private final UmsAdmin umsAdmin; + //拥有资源列表 + private final List resourceList; + + public AdminUserDetails(UmsAdmin umsAdmin, List resourceList) { + this.umsAdmin = umsAdmin; + this.resourceList = resourceList; + } + + @Override + public Collection getAuthorities() { + //返回当前用户所拥有的资源 + return resourceList.stream() + .map(resource ->new SimpleGrantedAuthority(resource.getId()+":"+resource.getName())) + .collect(Collectors.toList()); + } + + @Override + public String getPassword() { + return umsAdmin.getPassword(); + } + + @Override + public String getUsername() { + return umsAdmin.getUsername(); + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return umsAdmin.getStatus().equals(1); + } +} diff --git a/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsAdmin.java b/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsAdmin.java new file mode 100644 index 0000000..431ad5e --- /dev/null +++ b/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsAdmin.java @@ -0,0 +1,39 @@ +package com.teaching.backend.model.entity.umsAdmin; + +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; +import java.time.LocalDateTime; + +@Data +@TableName("ums_admin") +public class UmsAdmin implements Serializable { + + //主键 + @TableId(type = IdType.AUTO) + private Long id; + + //用户名 + private String username; + + //密码 + private String password; + + //手机号 + private String phone; + + //昵称 + private String nickName; + + //头像 + private String icon; + + //注册时间 + private LocalDateTime createTime; + + //账号状态 + private Integer status; +} diff --git a/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsAdminExample.java b/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsAdminExample.java new file mode 100644 index 0000000..685731b --- /dev/null +++ b/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsAdminExample.java @@ -0,0 +1,860 @@ +package com.teaching.backend.model.entity.umsAdmin; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +public class UmsAdminExample { + protected String orderByClause; + + protected boolean distinct; + + protected List oredCriteria; + + public UmsAdminExample() { + oredCriteria = new ArrayList<>(); + } + + public void setOrderByClause(String orderByClause) { + this.orderByClause = orderByClause; + } + + public String getOrderByClause() { + return orderByClause; + } + + public void setDistinct(boolean distinct) { + this.distinct = distinct; + } + + public boolean isDistinct() { + return distinct; + } + + public List getOredCriteria() { + return oredCriteria; + } + + public void or(Criteria criteria) { + oredCriteria.add(criteria); + } + + public Criteria or() { + Criteria criteria = createCriteriaInternal(); + oredCriteria.add(criteria); + return criteria; + } + + public Criteria createCriteria() { + Criteria criteria = createCriteriaInternal(); + if (oredCriteria.size() == 0) { + oredCriteria.add(criteria); + } + return criteria; + } + + protected Criteria createCriteriaInternal() { + Criteria criteria = new Criteria(); + return criteria; + } + + public void clear() { + oredCriteria.clear(); + orderByClause = null; + distinct = false; + } + + protected abstract static class GeneratedCriteria { + protected List criteria; + + protected GeneratedCriteria() { + super(); + criteria = new ArrayList<>(); + } + + public boolean isValid() { + return criteria.size() > 0; + } + + public List getAllCriteria() { + return criteria; + } + + public List getCriteria() { + return criteria; + } + + protected void addCriterion(String condition) { + if (condition == null) { + throw new RuntimeException("Value for condition cannot be null"); + } + criteria.add(new Criterion(condition)); + } + + protected void addCriterion(String condition, Object value, String property) { + if (value == null) { + throw new RuntimeException("Value for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value)); + } + + protected void addCriterion(String condition, Object value1, Object value2, String property) { + if (value1 == null || value2 == null) { + throw new RuntimeException("Between values for " + property + " cannot be null"); + } + criteria.add(new Criterion(condition, value1, value2)); + } + + public Criteria andIdIsNull() { + addCriterion("id is null"); + return (Criteria) this; + } + + public Criteria andIdIsNotNull() { + addCriterion("id is not null"); + return (Criteria) this; + } + + public Criteria andIdEqualTo(Long value) { + addCriterion("id =", value, "id"); + return (Criteria) this; + } + + public Criteria andIdNotEqualTo(Long value) { + addCriterion("id <>", value, "id"); + return (Criteria) this; + } + + public Criteria andIdGreaterThan(Long value) { + addCriterion("id >", value, "id"); + return (Criteria) this; + } + + public Criteria andIdGreaterThanOrEqualTo(Long value) { + addCriterion("id >=", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLessThan(Long value) { + addCriterion("id <", value, "id"); + return (Criteria) this; + } + + public Criteria andIdLessThanOrEqualTo(Long value) { + addCriterion("id <=", value, "id"); + return (Criteria) this; + } + + public Criteria andIdIn(List values) { + addCriterion("id in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdNotIn(List values) { + addCriterion("id not in", values, "id"); + return (Criteria) this; + } + + public Criteria andIdBetween(Long value1, Long value2) { + addCriterion("id between", value1, value2, "id"); + return (Criteria) this; + } + + public Criteria andIdNotBetween(Long value1, Long value2) { + addCriterion("id not between", value1, value2, "id"); + return (Criteria) this; + } + + public Criteria andUsernameIsNull() { + addCriterion("username is null"); + return (Criteria) this; + } + + public Criteria andUsernameIsNotNull() { + addCriterion("username is not null"); + return (Criteria) this; + } + + public Criteria andUsernameEqualTo(String value) { + addCriterion("username =", value, "username"); + return (Criteria) this; + } + + public Criteria andUsernameNotEqualTo(String value) { + addCriterion("username <>", value, "username"); + return (Criteria) this; + } + + public Criteria andUsernameGreaterThan(String value) { + addCriterion("username >", value, "username"); + return (Criteria) this; + } + + public Criteria andUsernameGreaterThanOrEqualTo(String value) { + addCriterion("username >=", value, "username"); + return (Criteria) this; + } + + public Criteria andUsernameLessThan(String value) { + addCriterion("username <", value, "username"); + return (Criteria) this; + } + + public Criteria andUsernameLessThanOrEqualTo(String value) { + addCriterion("username <=", value, "username"); + return (Criteria) this; + } + + public Criteria andUsernameLike(String value) { + addCriterion("username like", value, "username"); + return (Criteria) this; + } + + public Criteria andUsernameNotLike(String value) { + addCriterion("username not like", value, "username"); + return (Criteria) this; + } + + public Criteria andUsernameIn(List values) { + addCriterion("username in", values, "username"); + return (Criteria) this; + } + + public Criteria andUsernameNotIn(List values) { + addCriterion("username not in", values, "username"); + return (Criteria) this; + } + + public Criteria andUsernameBetween(String value1, String value2) { + addCriterion("username between", value1, value2, "username"); + return (Criteria) this; + } + + public Criteria andUsernameNotBetween(String value1, String value2) { + addCriterion("username not between", value1, value2, "username"); + return (Criteria) this; + } + + public Criteria andPasswordIsNull() { + addCriterion("password is null"); + return (Criteria) this; + } + + public Criteria andPasswordIsNotNull() { + addCriterion("password is not null"); + return (Criteria) this; + } + + public Criteria andPasswordEqualTo(String value) { + addCriterion("password =", value, "password"); + return (Criteria) this; + } + + public Criteria andPasswordNotEqualTo(String value) { + addCriterion("password <>", value, "password"); + return (Criteria) this; + } + + public Criteria andPasswordGreaterThan(String value) { + addCriterion("password >", value, "password"); + return (Criteria) this; + } + + public Criteria andPasswordGreaterThanOrEqualTo(String value) { + addCriterion("password >=", value, "password"); + return (Criteria) this; + } + + public Criteria andPasswordLessThan(String value) { + addCriterion("password <", value, "password"); + return (Criteria) this; + } + + public Criteria andPasswordLessThanOrEqualTo(String value) { + addCriterion("password <=", value, "password"); + return (Criteria) this; + } + + public Criteria andPasswordLike(String value) { + addCriterion("password like", value, "password"); + return (Criteria) this; + } + + public Criteria andPasswordNotLike(String value) { + addCriterion("password not like", value, "password"); + return (Criteria) this; + } + + public Criteria andPasswordIn(List values) { + addCriterion("password in", values, "password"); + return (Criteria) this; + } + + public Criteria andPasswordNotIn(List values) { + addCriterion("password not in", values, "password"); + return (Criteria) this; + } + + public Criteria andPasswordBetween(String value1, String value2) { + addCriterion("password between", value1, value2, "password"); + return (Criteria) this; + } + + public Criteria andPasswordNotBetween(String value1, String value2) { + addCriterion("password not between", value1, value2, "password"); + return (Criteria) this; + } + + public Criteria andIconIsNull() { + addCriterion("icon is null"); + return (Criteria) this; + } + + public Criteria andIconIsNotNull() { + addCriterion("icon is not null"); + return (Criteria) this; + } + + public Criteria andIconEqualTo(String value) { + addCriterion("icon =", value, "icon"); + return (Criteria) this; + } + + public Criteria andIconNotEqualTo(String value) { + addCriterion("icon <>", value, "icon"); + return (Criteria) this; + } + + public Criteria andIconGreaterThan(String value) { + addCriterion("icon >", value, "icon"); + return (Criteria) this; + } + + public Criteria andIconGreaterThanOrEqualTo(String value) { + addCriterion("icon >=", value, "icon"); + return (Criteria) this; + } + + public Criteria andIconLessThan(String value) { + addCriterion("icon <", value, "icon"); + return (Criteria) this; + } + + public Criteria andIconLessThanOrEqualTo(String value) { + addCriterion("icon <=", value, "icon"); + return (Criteria) this; + } + + public Criteria andIconLike(String value) { + addCriterion("icon like", value, "icon"); + return (Criteria) this; + } + + public Criteria andIconNotLike(String value) { + addCriterion("icon not like", value, "icon"); + return (Criteria) this; + } + + public Criteria andIconIn(List values) { + addCriterion("icon in", values, "icon"); + return (Criteria) this; + } + + public Criteria andIconNotIn(List values) { + addCriterion("icon not in", values, "icon"); + return (Criteria) this; + } + + public Criteria andIconBetween(String value1, String value2) { + addCriterion("icon between", value1, value2, "icon"); + return (Criteria) this; + } + + public Criteria andIconNotBetween(String value1, String value2) { + addCriterion("icon not between", value1, value2, "icon"); + return (Criteria) this; + } + + public Criteria andEmailIsNull() { + addCriterion("email is null"); + return (Criteria) this; + } + + public Criteria andEmailIsNotNull() { + addCriterion("email is not null"); + return (Criteria) this; + } + + public Criteria andEmailEqualTo(String value) { + addCriterion("email =", value, "email"); + return (Criteria) this; + } + + public Criteria andEmailNotEqualTo(String value) { + addCriterion("email <>", value, "email"); + return (Criteria) this; + } + + public Criteria andEmailGreaterThan(String value) { + addCriterion("email >", value, "email"); + return (Criteria) this; + } + + public Criteria andEmailGreaterThanOrEqualTo(String value) { + addCriterion("email >=", value, "email"); + return (Criteria) this; + } + + public Criteria andEmailLessThan(String value) { + addCriterion("email <", value, "email"); + return (Criteria) this; + } + + public Criteria andEmailLessThanOrEqualTo(String value) { + addCriterion("email <=", value, "email"); + return (Criteria) this; + } + + public Criteria andEmailLike(String value) { + addCriterion("email like", value, "email"); + return (Criteria) this; + } + + public Criteria andEmailNotLike(String value) { + addCriterion("email not like", value, "email"); + return (Criteria) this; + } + + public Criteria andEmailIn(List values) { + addCriterion("email in", values, "email"); + return (Criteria) this; + } + + public Criteria andEmailNotIn(List values) { + addCriterion("email not in", values, "email"); + return (Criteria) this; + } + + public Criteria andEmailBetween(String value1, String value2) { + addCriterion("email between", value1, value2, "email"); + return (Criteria) this; + } + + public Criteria andEmailNotBetween(String value1, String value2) { + addCriterion("email not between", value1, value2, "email"); + return (Criteria) this; + } + + public Criteria andNickNameIsNull() { + addCriterion("nick_name is null"); + return (Criteria) this; + } + + public Criteria andNickNameIsNotNull() { + addCriterion("nick_name is not null"); + return (Criteria) this; + } + + public Criteria andNickNameEqualTo(String value) { + addCriterion("nick_name =", value, "nickName"); + return (Criteria) this; + } + + public Criteria andNickNameNotEqualTo(String value) { + addCriterion("nick_name <>", value, "nickName"); + return (Criteria) this; + } + + public Criteria andNickNameGreaterThan(String value) { + addCriterion("nick_name >", value, "nickName"); + return (Criteria) this; + } + + public Criteria andNickNameGreaterThanOrEqualTo(String value) { + addCriterion("nick_name >=", value, "nickName"); + return (Criteria) this; + } + + public Criteria andNickNameLessThan(String value) { + addCriterion("nick_name <", value, "nickName"); + return (Criteria) this; + } + + public Criteria andNickNameLessThanOrEqualTo(String value) { + addCriterion("nick_name <=", value, "nickName"); + return (Criteria) this; + } + + public Criteria andNickNameLike(String value) { + addCriterion("nick_name like", value, "nickName"); + return (Criteria) this; + } + + public Criteria andNickNameNotLike(String value) { + addCriterion("nick_name not like", value, "nickName"); + return (Criteria) this; + } + + public Criteria andNickNameIn(List values) { + addCriterion("nick_name in", values, "nickName"); + return (Criteria) this; + } + + public Criteria andNickNameNotIn(List values) { + addCriterion("nick_name not in", values, "nickName"); + return (Criteria) this; + } + + public Criteria andNickNameBetween(String value1, String value2) { + addCriterion("nick_name between", value1, value2, "nickName"); + return (Criteria) this; + } + + public Criteria andNickNameNotBetween(String value1, String value2) { + addCriterion("nick_name not between", value1, value2, "nickName"); + return (Criteria) this; + } + + public Criteria andNoteIsNull() { + addCriterion("note is null"); + return (Criteria) this; + } + + public Criteria andNoteIsNotNull() { + addCriterion("note is not null"); + return (Criteria) this; + } + + public Criteria andNoteEqualTo(String value) { + addCriterion("note =", value, "note"); + return (Criteria) this; + } + + public Criteria andNoteNotEqualTo(String value) { + addCriterion("note <>", value, "note"); + return (Criteria) this; + } + + public Criteria andNoteGreaterThan(String value) { + addCriterion("note >", value, "note"); + return (Criteria) this; + } + + public Criteria andNoteGreaterThanOrEqualTo(String value) { + addCriterion("note >=", value, "note"); + return (Criteria) this; + } + + public Criteria andNoteLessThan(String value) { + addCriterion("note <", value, "note"); + return (Criteria) this; + } + + public Criteria andNoteLessThanOrEqualTo(String value) { + addCriterion("note <=", value, "note"); + return (Criteria) this; + } + + public Criteria andNoteLike(String value) { + addCriterion("note like", value, "note"); + return (Criteria) this; + } + + public Criteria andNoteNotLike(String value) { + addCriterion("note not like", value, "note"); + return (Criteria) this; + } + + public Criteria andNoteIn(List values) { + addCriterion("note in", values, "note"); + return (Criteria) this; + } + + public Criteria andNoteNotIn(List values) { + addCriterion("note not in", values, "note"); + return (Criteria) this; + } + + public Criteria andNoteBetween(String value1, String value2) { + addCriterion("note between", value1, value2, "note"); + return (Criteria) this; + } + + public Criteria andNoteNotBetween(String value1, String value2) { + addCriterion("note not between", value1, value2, "note"); + return (Criteria) this; + } + + public Criteria andCreateTimeIsNull() { + addCriterion("create_time is null"); + return (Criteria) this; + } + + public Criteria andCreateTimeIsNotNull() { + addCriterion("create_time is not null"); + return (Criteria) this; + } + + public Criteria andCreateTimeEqualTo(Date value) { + addCriterion("create_time =", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeNotEqualTo(Date value) { + addCriterion("create_time <>", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeGreaterThan(Date value) { + addCriterion("create_time >", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeGreaterThanOrEqualTo(Date value) { + addCriterion("create_time >=", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeLessThan(Date value) { + addCriterion("create_time <", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeLessThanOrEqualTo(Date value) { + addCriterion("create_time <=", value, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeIn(List values) { + addCriterion("create_time in", values, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeNotIn(List values) { + addCriterion("create_time not in", values, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeBetween(Date value1, Date value2) { + addCriterion("create_time between", value1, value2, "createTime"); + return (Criteria) this; + } + + public Criteria andCreateTimeNotBetween(Date value1, Date value2) { + addCriterion("create_time not between", value1, value2, "createTime"); + return (Criteria) this; + } + + public Criteria andLoginTimeIsNull() { + addCriterion("login_time is null"); + return (Criteria) this; + } + + public Criteria andLoginTimeIsNotNull() { + addCriterion("login_time is not null"); + return (Criteria) this; + } + + public Criteria andLoginTimeEqualTo(Date value) { + addCriterion("login_time =", value, "loginTime"); + return (Criteria) this; + } + + public Criteria andLoginTimeNotEqualTo(Date value) { + addCriterion("login_time <>", value, "loginTime"); + return (Criteria) this; + } + + public Criteria andLoginTimeGreaterThan(Date value) { + addCriterion("login_time >", value, "loginTime"); + return (Criteria) this; + } + + public Criteria andLoginTimeGreaterThanOrEqualTo(Date value) { + addCriterion("login_time >=", value, "loginTime"); + return (Criteria) this; + } + + public Criteria andLoginTimeLessThan(Date value) { + addCriterion("login_time <", value, "loginTime"); + return (Criteria) this; + } + + public Criteria andLoginTimeLessThanOrEqualTo(Date value) { + addCriterion("login_time <=", value, "loginTime"); + return (Criteria) this; + } + + public Criteria andLoginTimeIn(List values) { + addCriterion("login_time in", values, "loginTime"); + return (Criteria) this; + } + + public Criteria andLoginTimeNotIn(List values) { + addCriterion("login_time not in", values, "loginTime"); + return (Criteria) this; + } + + public Criteria andLoginTimeBetween(Date value1, Date value2) { + addCriterion("login_time between", value1, value2, "loginTime"); + return (Criteria) this; + } + + public Criteria andLoginTimeNotBetween(Date value1, Date value2) { + addCriterion("login_time not between", value1, value2, "loginTime"); + return (Criteria) this; + } + + public Criteria andStatusIsNull() { + addCriterion("status is null"); + return (Criteria) this; + } + + public Criteria andStatusIsNotNull() { + addCriterion("status is not null"); + return (Criteria) this; + } + + public Criteria andStatusEqualTo(Integer value) { + addCriterion("status =", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusNotEqualTo(Integer value) { + addCriterion("status <>", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusGreaterThan(Integer value) { + addCriterion("status >", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusGreaterThanOrEqualTo(Integer value) { + addCriterion("status >=", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusLessThan(Integer value) { + addCriterion("status <", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusLessThanOrEqualTo(Integer value) { + addCriterion("status <=", value, "status"); + return (Criteria) this; + } + + public Criteria andStatusIn(List values) { + addCriterion("status in", values, "status"); + return (Criteria) this; + } + + public Criteria andStatusNotIn(List values) { + addCriterion("status not in", values, "status"); + return (Criteria) this; + } + + public Criteria andStatusBetween(Integer value1, Integer value2) { + addCriterion("status between", value1, value2, "status"); + return (Criteria) this; + } + + public Criteria andStatusNotBetween(Integer value1, Integer value2) { + addCriterion("status not between", value1, value2, "status"); + return (Criteria) this; + } + } + + public static class Criteria extends GeneratedCriteria { + protected Criteria() { + super(); + } + } + + public static class Criterion { + private String condition; + + private Object value; + + private Object secondValue; + + private boolean noValue; + + private boolean singleValue; + + private boolean betweenValue; + + private boolean listValue; + + private String typeHandler; + + public String getCondition() { + return condition; + } + + public Object getValue() { + return value; + } + + public Object getSecondValue() { + return secondValue; + } + + public boolean isNoValue() { + return noValue; + } + + public boolean isSingleValue() { + return singleValue; + } + + public boolean isBetweenValue() { + return betweenValue; + } + + public boolean isListValue() { + return listValue; + } + + public String getTypeHandler() { + return typeHandler; + } + + protected Criterion(String condition) { + super(); + this.condition = condition; + this.typeHandler = null; + this.noValue = true; + } + + protected Criterion(String condition, Object value, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.typeHandler = typeHandler; + if (value instanceof List) { + this.listValue = true; + } else { + this.singleValue = true; + } + } + + protected Criterion(String condition, Object value) { + this(condition, value, null); + } + + protected Criterion(String condition, Object value, Object secondValue, String typeHandler) { + super(); + this.condition = condition; + this.value = value; + this.secondValue = secondValue; + this.typeHandler = typeHandler; + this.betweenValue = true; + } + + protected Criterion(String condition, Object value, Object secondValue) { + this(condition, value, secondValue, null); + } + } +} diff --git a/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsAdminRoleRelation.java b/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsAdminRoleRelation.java new file mode 100644 index 0000000..10734ee --- /dev/null +++ b/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsAdminRoleRelation.java @@ -0,0 +1,18 @@ +package com.teaching.backend.model.entity.umsAdmin; + +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.Data; + +import java.io.Serializable; + +@Data +@TableName("ums_admin_role_relation") +public class UmsAdminRoleRelation implements Serializable { + private Long id; + + private Long adminId; + + private Long roleId; + + private static final long serialVersionUID = 1L; +} diff --git a/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsMenu.java b/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsMenu.java new file mode 100644 index 0000000..64b4d0b --- /dev/null +++ b/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsMenu.java @@ -0,0 +1,41 @@ +package com.teaching.backend.model.entity.umsAdmin; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("ums_menu") +public class UmsMenu implements Serializable { + private Long id; + + @ApiModelProperty(value = "父级ID") + private Long parentId; + + @ApiModelProperty(value = "创建时间") + private Date createTime; + + @ApiModelProperty(value = "菜单名称") + private String title; + + @ApiModelProperty(value = "菜单级数") + private Integer level; + + @ApiModelProperty(value = "菜单排序") + private Integer sort; + + @ApiModelProperty(value = "前端名称") + private String name; + + @ApiModelProperty(value = "前端图标") + private String icon; + + @ApiModelProperty(value = "前端隐藏") + private Integer hidden; + + private static final long serialVersionUID = 1L; + +} diff --git a/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsResource.java b/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsResource.java new file mode 100644 index 0000000..aa1a245 --- /dev/null +++ b/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsResource.java @@ -0,0 +1,33 @@ +package com.teaching.backend.model.entity.umsAdmin; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; + +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("ums_resource") +public class UmsResource implements Serializable { + private Long id; + + @ApiModelProperty(value = "创建时间") + private Date createTime; + + @ApiModelProperty(value = "资源名称") + private String name; + + @ApiModelProperty(value = "资源URL") + private String url; + + @ApiModelProperty(value = "描述") + private String description; + + @ApiModelProperty(value = "资源分类ID") + private Long categoryId; + +// private static final long serialVersionUID = 1L; + + +} diff --git a/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsRole.java b/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsRole.java new file mode 100644 index 0000000..eaeb260 --- /dev/null +++ b/src/main/java/com/teaching/backend/model/entity/umsAdmin/UmsRole.java @@ -0,0 +1,33 @@ +package com.teaching.backend.model.entity.umsAdmin; + +import com.baomidou.mybatisplus.annotation.TableName; +import io.swagger.annotations.ApiModelProperty; +import lombok.Data; +import java.io.Serializable; +import java.util.Date; + +@Data +@TableName("ums_role") +public class UmsRole implements Serializable { + private Long id; + + @ApiModelProperty(value = "名称") + private String name; + + @ApiModelProperty(value = "描述") + private String description; + + @ApiModelProperty(value = "后台用户数量") + private Integer adminCount; + + @ApiModelProperty(value = "创建时间") + private Date createTime; + + @ApiModelProperty(value = "启用状态:0->禁用;1->启用") + private Integer status; + + private Integer sort; + + private static final long serialVersionUID = 1L; + +} diff --git a/src/main/java/com/teaching/backend/model/enums/test1.java b/src/main/java/com/teaching/backend/model/enums/test1.java deleted file mode 100644 index e44d816..0000000 --- a/src/main/java/com/teaching/backend/model/enums/test1.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.teaching.backend.model.enums; - -/** - * @Author:youhang - * @Date:2024-05-30-18:20 - * @Description: - */ -public class test1 { -} diff --git a/src/main/java/com/teaching/backend/model/vo/records/LearningRecordsVo.java b/src/main/java/com/teaching/backend/model/vo/records/LearningRecordsVo.java index e9b3ab2..75b2550 100644 --- a/src/main/java/com/teaching/backend/model/vo/records/LearningRecordsVo.java +++ b/src/main/java/com/teaching/backend/model/vo/records/LearningRecordsVo.java @@ -1,59 +1,59 @@ -package com.teaching.backend.model.vo.records; - -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.experimental.Accessors; - -@Data -@EqualsAndHashCode(callSuper = false) -@Accessors(chain = true) -public class LearningRecordsVo { -// private static final long serialVersionUID = 1L; - - /** - * 内部编号 - */ - private String id; - - /** - * 课程名称 - */ - private String coursesName; - +//package com.teaching.backend.model.vo.records; +// +//import lombok.Data; +//import lombok.EqualsAndHashCode; +//import lombok.experimental.Accessors; +// +//@Data +//@EqualsAndHashCode(callSuper = false) +//@Accessors(chain = true) +//public class LearningRecordsVo { +//// private static final long serialVersionUID = 1L; +// // /** -// * 资源类型 +// * 内部编号 // */ -// private String type; - - /** - * 封面 - */ - private String content; - - /** - * 资源观看人数 - */ - private Long number; - - - /** - * 上次观看时间 - */ - private String time; - /** - * 地址 - */ - private String address; +// private String id; +// // /** -// * 创建日期 +// * 课程名称 // */ -// private LocalDateTime createTime; +// private String coursesName; +// +//// /** +//// * 资源类型 +//// */ +//// private String type; // // /** -// * 更新日期 +// * 封面 // */ -// private LocalDateTime updateTime; - - - -} +// private String content; +// +// /** +// * 资源观看人数 +// */ +// private Long number; +// +// +// /** +// * 上次观看时间 +// */ +// private String time; +// /** +// * 地址 +// */ +// private String address; +//// /** +//// * 创建日期 +//// */ +//// private LocalDateTime createTime; +//// +//// /** +//// * 更新日期 +//// */ +//// private LocalDateTime updateTime; +// +// +// +//} diff --git a/src/main/java/com/teaching/backend/model/vo/test1.java b/src/main/java/com/teaching/backend/model/vo/test1.java deleted file mode 100644 index ae377d9..0000000 --- a/src/main/java/com/teaching/backend/model/vo/test1.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.teaching.backend.model.vo; - -/** - * @Author:youhang - * @Date:2024-05-30-18:20 - * @Description: - */ -public class test1 { -} diff --git a/src/main/java/com/teaching/backend/service/umsAdmin/UmsAdminService.java b/src/main/java/com/teaching/backend/service/umsAdmin/UmsAdminService.java new file mode 100644 index 0000000..5dd107d --- /dev/null +++ b/src/main/java/com/teaching/backend/service/umsAdmin/UmsAdminService.java @@ -0,0 +1,74 @@ +package com.teaching.backend.service.umsAdmin; + +import com.baomidou.mybatisplus.extension.service.IService; +import com.teaching.backend.model.dto.UmsAdminParam; +import com.teaching.backend.model.dto.UpdateAdminPasswordParam; +import com.teaching.backend.model.entity.umsAdmin.UmsAdmin; +import com.teaching.backend.model.entity.umsAdmin.UmsResource; +import com.teaching.backend.model.entity.umsAdmin.UmsRole; +import org.springframework.security.core.userdetails.UserDetails; + +import java.util.List; + +public interface UmsAdminService extends IService { + + /** + * 注册功能 + */ + UmsAdmin register(UmsAdminParam umsAdminParam); + + /** + * 登录功能 + * @param username 用户名 + * @param password 密码 + * @return 生成的JWT的token + */ + String login(String username, String password); + + + /** + * 根据用户名获取后台管理员 + */ + UmsAdmin getAdminByUsername(String username); + + /** + * 获取指定用户的可访问的资源 + */ + List getResourceList(Long adminId); + + /** + * 获取用户信息 + */ + UserDetails loadUserByUsername(String username); + + /** + * 刷新token的功能 + * @param oldToken 旧的token + */ + String refreshToken(String oldToken); + + /** + * 获取用户对应角色 + */ + List getRoleList(Long adminId); + + /** + * 修改指定用户信息 + */ + boolean updateUms(UmsAdmin umsadmin); + + /** + * 修改密码 + */ + int updatePassword(UpdateAdminPasswordParam updatePasswordParam); + + /** + * 发送短信 + */ + String sendVerifyCode(String phone); + + /** + * 手机号注册 + */ + UmsAdmin phoneRegister(UmsAdminParam umsAdminParam); +} diff --git a/src/main/java/com/teaching/backend/service/umsAdmin/UmsRoleService.java b/src/main/java/com/teaching/backend/service/umsAdmin/UmsRoleService.java new file mode 100644 index 0000000..4eb76ef --- /dev/null +++ b/src/main/java/com/teaching/backend/service/umsAdmin/UmsRoleService.java @@ -0,0 +1,21 @@ +package com.teaching.backend.service.umsAdmin; + +import com.teaching.backend.model.entity.umsAdmin.UmsMenu; +import com.teaching.backend.model.entity.umsAdmin.UmsResource; +import com.teaching.backend.model.entity.umsAdmin.UmsRole; +import org.springframework.transaction.annotation.Transactional; + +import java.util.List; + +/** + * 后台角色管理Service + * Created by macro on 2018/9/30. + */ +public interface UmsRoleService { + + /** + * 根据管理员ID获取对应菜单 + */ + List getMenuList(Long adminId); + +} diff --git a/src/main/java/com/teaching/backend/service/umsAdmin/impl/UmsAdminServiceImpl.java b/src/main/java/com/teaching/backend/service/umsAdmin/impl/UmsAdminServiceImpl.java new file mode 100644 index 0000000..710ba6d --- /dev/null +++ b/src/main/java/com/teaching/backend/service/umsAdmin/impl/UmsAdminServiceImpl.java @@ -0,0 +1,271 @@ +package com.teaching.backend.service.umsAdmin.impl; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.StrUtil; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsRequest; +import com.aliyuncs.dysmsapi.model.v20170525.SendSmsResponse; +import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl; +import com.google.gson.Gson; +import com.teaching.backend.exception.Asserts; +import com.teaching.backend.exception.LyException; +import com.teaching.backend.mapper.umsAdmin.UmsAdminMapper; +import com.teaching.backend.mapper.umsAdmin.UmsAdminRoleRelationMapper; +import com.teaching.backend.model.dto.UmsAdminParam; +import com.teaching.backend.model.dto.UpdateAdminPasswordParam; +import com.teaching.backend.model.entity.umsAdmin.AdminUserDetails; +import com.teaching.backend.model.entity.umsAdmin.UmsAdmin; +import com.teaching.backend.model.entity.umsAdmin.UmsResource; +import com.teaching.backend.model.entity.umsAdmin.UmsRole; +import com.teaching.backend.service.umsAdmin.UmsAdminService; +import com.teaching.backend.utils.JwtTokenUtil; +import com.teaching.backend.utils.RegexUtils; +import lombok.extern.slf4j.Slf4j; +import org.apache.commons.lang3.RandomStringUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.amqp.core.AmqpTemplate; +import org.springframework.beans.BeanUtils; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.AuthenticationException; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.stereotype.Service; + +import com.aliyuncs.DefaultAcsClient; +import com.aliyuncs.IAcsClient; +import com.aliyuncs.exceptions.ClientException; +import com.aliyuncs.exceptions.ServerException; +import com.aliyuncs.profile.DefaultProfile; + + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Random; +import java.util.UUID; +import java.util.concurrent.TimeUnit; + +@Service +@Slf4j +public class UmsAdminServiceImpl extends ServiceImpl implements UmsAdminService { + + private static final String CHARACTERS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"; + private static final int USERNAME_LENGTH = 10; // 用户名长度 + private static final Logger LOGGER = LoggerFactory.getLogger(UmsAdminServiceImpl.class); + @Autowired + private JwtTokenUtil jwtTokenUtil; + @Autowired + private PasswordEncoder passwordEncoder; + @Autowired + private UmsAdminRoleRelationMapper adminRoleRelation; + @Autowired + private AmqpTemplate amqpTemplate; + @Autowired + private StringRedisTemplate redisTemplate; + + private final String KEY_PREFIX = "ly:sms:phone:"; + + @Override + public UmsAdmin register(UmsAdminParam umsAdminParam) { + UmsAdmin umsAdmin = new UmsAdmin(); + BeanUtils.copyProperties(umsAdminParam, umsAdmin); + umsAdmin.setCreateTime(LocalDateTime.now()); + umsAdmin.setStatus(1); + //查询是否有相同用户名的用户 + List umsAdminList = lambdaQuery() + .eq(UmsAdmin::getUsername, umsAdmin.getUsername()) + .list(); + if (umsAdminList.size() > 0) { + return null; + } + //将密码进行加密操作 + String encodePassword = passwordEncoder.encode(umsAdmin.getPassword()); + umsAdmin.setPassword(encodePassword); + save(umsAdmin); + return umsAdmin; + } + + @Override + public String login(String username, String password) { + String token = null; + //密码需要客户端加密后传递 + try { + UserDetails userDetails = loadUserByUsername(username); + if(!passwordEncoder.matches(password,userDetails.getPassword())){ + Asserts.fail("密码不正确"); + } + if(!userDetails.isEnabled()){ + Asserts.fail("帐号已被禁用"); + } + UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities()); + SecurityContextHolder.getContext().setAuthentication(authentication); + token = jwtTokenUtil.generateToken(userDetails); + } catch (AuthenticationException e) { + LOGGER.warn("登录异常:{}", e.getMessage()); + } + return token; + } + + @Override + public boolean updateUms(UmsAdmin umsadmin) { + if (umsadmin.getPassword().length() > 0){ + Asserts.fail("修改操作错误1"); + } + if (umsadmin.getCreateTime() != null){ + Asserts.fail("修改操作错误2"); + } + return updateById(umsadmin); + } + + @Override + public int updatePassword(UpdateAdminPasswordParam param) { + if(StrUtil.isEmpty(param.getUsername()) + ||StrUtil.isEmpty(param.getOldPassword()) + ||StrUtil.isEmpty(param.getNewPassword())){ + return -1; + } + List adminList = lambdaQuery() + .eq(UmsAdmin::getUsername, param.getUsername()) + .list(); + if(CollUtil.isEmpty(adminList)){ + return -2; + } + UmsAdmin umsAdmin = adminList.get(0); + if(!passwordEncoder.matches(param.getOldPassword(),umsAdmin.getPassword())){ + return -3; + } + umsAdmin.setPassword(passwordEncoder.encode(param.getNewPassword())); + updateById(umsAdmin); + return 1; + } + + @Override + public String sendVerifyCode(String phone) { + if (!RegexUtils.isPhone(phone)) { + throw new LyException(400, "手机号格式错误"); + } + + UmsAdmin admin = lambdaQuery() + .eq(UmsAdmin::getPhone, phone) + .one(); + if (admin != null){ +// throw new ; + return null; + } + + String code = RandomStringUtils.randomNumeric(5); + + String ALIBABA_CLOUD_ACCESS_KEY_ID = "LTAI5tF7fcDC5VTj1cVWKDU6"; + String ALIBABA_CLOUD_ACCESS_KEY_SECRET = "T7kQwaOxqWgmKzTZkzpCaPVhJuaw4T"; + + DefaultProfile profile = DefaultProfile.getProfile("cn-hangzhou", ALIBABA_CLOUD_ACCESS_KEY_ID, ALIBABA_CLOUD_ACCESS_KEY_SECRET); + IAcsClient client = new DefaultAcsClient(profile); + + SendSmsRequest request = new SendSmsRequest(); + request.setPhoneNumbers(phone); + request.setSignName("智慧系统"); + request.setTemplateCode("SMS_468225027"); + request.setTemplateParam("{\"code\":\""+code+"\"}"); + + try { + SendSmsResponse response = client.getAcsResponse(request); + System.out.println("11112"+new Gson().toJson(response)); + } catch (ServerException e) { + e.printStackTrace(); + } catch (ClientException e) { + System.out.println("ErrCode:" + e.getErrCode()); + System.out.println("ErrMsg:" + e.getErrMsg()); + System.out.println("RequestId:" + e.getRequestId()); + } + + //存入,redis,存5min + this.redisTemplate.opsForValue().set(KEY_PREFIX + phone, code, 5, TimeUnit.MINUTES); + + return code; + } + + @Override + public UmsAdmin phoneRegister(UmsAdminParam umsAdminParam) { + UmsAdmin umsAdmin = new UmsAdmin(); + BeanUtils.copyProperties(umsAdminParam, umsAdmin); + umsAdmin.setCreateTime(LocalDateTime.now()); + umsAdmin.setStatus(1); + //查询是否有相同手机号的用户 + List umsAdminList = lambdaQuery() + .eq(UmsAdmin::getPhone,umsAdminParam.getPhone()) + .list(); + if (umsAdminList.size() > 0 ) { + return null; + } + + //将密码进行加密操作 + String encodePassword = passwordEncoder.encode(umsAdmin.getPassword()); + umsAdmin.setUsername(randomUsername()); + umsAdmin.setPassword(encodePassword); + save(umsAdmin); + return umsAdmin; + } + + /* + 随机生成用户名 + */ + private String randomUsername(){ + String username; + UmsAdmin newUsername = new UmsAdmin(); + do { + UUID uuid = UUID.randomUUID(); + // 这里只是简单地截取UUID的一部分作为用户名,但你可以根据需要进行更复杂的处理 + username = uuid.toString().substring(0, 10); // 截取前10个字符作 + newUsername = lambdaQuery().eq(UmsAdmin::getUsername, username) + .one(); + } while ( newUsername != null); // 如果用户名已存在,则重新生成 + + return username; + } + + @Override + public String refreshToken(String oldToken) { + return jwtTokenUtil.refreshHeadToken(oldToken); + } + + @Override + public List getRoleList(Long adminId) { + return adminRoleRelation.getRoleList(adminId); + } + + + + @Override + public UmsAdmin getAdminByUsername(String username) { + //从数据库中获取 + UmsAdmin admin = lambdaQuery().eq(UmsAdmin::getUsername, username) + .one(); + if (admin != null) { + return admin; + } + return null; + } + + + @Override + public List getResourceList(Long adminId) { + //从数据库中获取 + List resourceList = adminRoleRelation.getResourceList(adminId); + return resourceList; + } + + @Override + public UserDetails loadUserByUsername(String username){ + //获取用户信息 + UmsAdmin admin = getAdminByUsername(username); + if (admin != null) { + List resourceList = getResourceList(admin.getId()); + return new AdminUserDetails(admin,resourceList); + } + throw new UsernameNotFoundException("用户名或密码错误"); + } + +} diff --git a/src/main/java/com/teaching/backend/service/umsAdmin/impl/UmsRoleServiceImpl.java b/src/main/java/com/teaching/backend/service/umsAdmin/impl/UmsRoleServiceImpl.java new file mode 100644 index 0000000..b3c8d29 --- /dev/null +++ b/src/main/java/com/teaching/backend/service/umsAdmin/impl/UmsRoleServiceImpl.java @@ -0,0 +1,26 @@ +package com.teaching.backend.service.umsAdmin.impl; + +import com.teaching.backend.mapper.umsAdmin.UmsRoleMapper; +import com.teaching.backend.model.entity.umsAdmin.UmsMenu; +import com.teaching.backend.model.entity.umsAdmin.UmsRole; +import com.teaching.backend.service.umsAdmin.UmsRoleService; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.util.List; + +/** + * 后台角色管理Service实现类 + * Created by macro on 2018/9/30. + */ +@Service +public class UmsRoleServiceImpl implements UmsRoleService { + + @Autowired + private UmsRoleMapper umsRoleMapper; + + @Override + public List getMenuList(Long adminId) { + return umsRoleMapper.getMenuList(adminId); + } +} diff --git a/src/main/java/com/teaching/backend/utils/JwtTokenUtil.java b/src/main/java/com/teaching/backend/utils/JwtTokenUtil.java new file mode 100644 index 0000000..ec1ee41 --- /dev/null +++ b/src/main/java/com/teaching/backend/utils/JwtTokenUtil.java @@ -0,0 +1,169 @@ +package com.teaching.backend.utils; + +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import io.jsonwebtoken.Claims; +import io.jsonwebtoken.Jwts; +import io.jsonwebtoken.SignatureAlgorithm; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.security.core.userdetails.UserDetails; +import java.util.Date; +import java.util.HashMap; +import java.util.Map; + +/** + * JwtToken生成的工具类 + * JWT token的格式:header.payload.signature + * header的格式(算法、token的类型): + * {"alg": "HS512","typ": "JWT"} + * payload的格式(用户名、创建时间、生成时间): + * {"sub":"wang","created":1489079981393,"exp":1489684781} + * signature的生成算法: + * HMACSHA512(base64UrlEncode(header) + "." +base64UrlEncode(payload),secret) + * Created by macro on 2018/4/26. + */ +public class JwtTokenUtil { + private static final Logger LOGGER = LoggerFactory.getLogger(JwtTokenUtil.class); + private static final String CLAIM_KEY_USERNAME = "sub"; + private static final String CLAIM_KEY_CREATED = "created"; + @Value("${jwt.secret}") + private String secret; + @Value("${jwt.expiration}") + private Long expiration; + @Value("${jwt.tokenHead}") + private String tokenHead; + + /** + * 根据负责生成JWT的token + */ + private String generateToken(Map claims) { + return Jwts.builder() + .setClaims(claims) + .setExpiration(generateExpirationDate()) + .signWith(SignatureAlgorithm.HS512, secret) + .compact(); + } + + /** + * 从token中获取JWT中的负载 + */ + private Claims getClaimsFromToken(String token) { + Claims claims = null; + try { + claims = Jwts.parser() + .setSigningKey(secret) + .parseClaimsJws(token) + .getBody(); + } catch (Exception e) { + LOGGER.info("JWT格式验证失败:{}", token); + } + return claims; + } + + /** + * 生成token的过期时间 + */ + private Date generateExpirationDate() { + return new Date(System.currentTimeMillis() + expiration * 1000); + } + + /** + * 从token中获取登录用户名 + */ + public String getUserNameFromToken(String token) { + String username; + try { + Claims claims = getClaimsFromToken(token); + username = claims.getSubject(); + } catch (Exception e) { + username = null; + } + return username; + } + + /** + * 验证token是否还有效 + * + * @param token 客户端传入的token + * @param userDetails 从数据库中查询出来的用户信息 + */ + public boolean validateToken(String token, UserDetails userDetails) { + String username = getUserNameFromToken(token); + return username.equals(userDetails.getUsername()) && !isTokenExpired(token); + } + + /** + * 判断token是否已经失效 + */ + private boolean isTokenExpired(String token) { + Date expiredDate = getExpiredDateFromToken(token); + return expiredDate.before(new Date()); + } + + /** + * 从token中获取过期时间 + */ + private Date getExpiredDateFromToken(String token) { + Claims claims = getClaimsFromToken(token); + return claims.getExpiration(); + } + + /** + * 根据用户信息生成token + */ + public String generateToken(UserDetails userDetails) { + Map claims = new HashMap<>(); + claims.put(CLAIM_KEY_USERNAME, userDetails.getUsername()); + claims.put(CLAIM_KEY_CREATED, new Date()); + return generateToken(claims); + } + + /** + * 当原来的token没过期时是可以刷新的 + * + * @param oldToken 带tokenHead的token + */ + public String refreshHeadToken(String oldToken) { + if(StrUtil.isEmpty(oldToken)){ + return null; + } + String token = oldToken.substring(tokenHead.length()); + if(StrUtil.isEmpty(token)){ + return null; + } + //token校验不通过 + Claims claims = getClaimsFromToken(token); + if(claims==null){ + return null; + } + //如果token已经过期,不支持刷新 + if(isTokenExpired(token)){ + return null; + } + //如果token在30分钟之内刚刷新过,返回原token + if(tokenRefreshJustBefore(token,30*60)){ + return token; + }else{ + claims.put(CLAIM_KEY_CREATED, new Date()); + return generateToken(claims); + } + } + + /** + * 判断token在指定时间内是否刚刚刷新过 + * @param token 原token + * @param time 指定时间(秒) + */ + private boolean tokenRefreshJustBefore(String token, int time) { + Claims claims = getClaimsFromToken(token); + Date created = claims.get(CLAIM_KEY_CREATED, Date.class); + Date refreshDate = new Date(); + //刷新时间在创建时间的指定时间内 + if(refreshDate.after(created)&&refreshDate.before(DateUtil.offsetSecond(created,time))){ + return true; + } + return false; + } +} diff --git a/src/main/java/com/teaching/backend/utils/RegexUtils.java b/src/main/java/com/teaching/backend/utils/RegexUtils.java new file mode 100644 index 0000000..69afcab --- /dev/null +++ b/src/main/java/com/teaching/backend/utils/RegexUtils.java @@ -0,0 +1,32 @@ +package com.teaching.backend.utils; + + +import com.baomidou.mybatisplus.core.toolkit.StringUtils; +import com.teaching.backend.constant.RegexPatterns; + +public class RegexUtils { + /** + * 是否符合手机格式 + * @param phone 要校验的手机号 + * @return true:符合,false:不符合 + */ + public static boolean isPhone(String phone){ + return matches(phone, RegexPatterns.PHONE_REGEX); + } + + /** + * 是否符合验证码格式 + * @param code 要校验的验证码 + * @return true:符合,false:不符合 + */ + public static boolean isCodeValid(String code){ + return matches(code, RegexPatterns.VERIFY_CODE_REGEX); + } + + private static boolean matches(String str, String regex){ + if (StringUtils.isBlank(str)) { + return false; + } + return str.matches(regex); + } +} diff --git a/src/main/java/com/teaching/backend/utils/ThreadLocalUtil.java b/src/main/java/com/teaching/backend/utils/ThreadLocalUtil.java new file mode 100644 index 0000000..2f7b0c7 --- /dev/null +++ b/src/main/java/com/teaching/backend/utils/ThreadLocalUtil.java @@ -0,0 +1,26 @@ +package com.teaching.backend.utils; + +/** + * ThreadLocal 工具类 + */ +@SuppressWarnings("all") +public class ThreadLocalUtil { + //提供ThreadLocal对象, + private static final ThreadLocal THREAD_LOCAL = new ThreadLocal(); + + //根据键获取值 + public static T get(){ + return (T) THREAD_LOCAL.get(); + } + + //存储键值对 + public static void set(Object value){ + THREAD_LOCAL.set(value); + } + + + //清除ThreadLocal 防止内存泄漏 + public static void remove(){ + THREAD_LOCAL.remove(); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 2a97162..57daa0b 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -10,22 +10,52 @@ spring: driver-class-name: com.mysql.cj.jdbc.Driver url: jdbc:mysql://localhost:3306/teaching_db username: root - password: 1234567788 + password: root mybatis: configuration: map-underscore-to-camel-case: true - mapper-locations: - - classpath:dao/*.xml - - classpath*:com/**/mapper/*.xml + +# 自定义jwt key +jwt: + tokenHeader: Authorization #JWT存储的请求头 + secret: mySecret #JWT加解密使用的密钥 + expiration: 604800 #JWT的超期限时间(60*60*24)一天 + tokenHead: Bearer #JWT负载中拿到开头 knife4j: enable: true openapi: - title: "" - version: 1.0 + title: 用户管理接口文档 + description: "用户管理接口文档" + concat: zjh + version: v1.0.0 group: default: + group-name: default api-rule: package api-rule-resources: - com.teaching.backend.controller +secure: + ignored: + urls: #安全路径白名单 + - /swagger-ui/ + - /swagger-resources/** + - /**/v2/api-docs + - /**/*.html + - /**/*.js + - /**/*.css + - /**/*.png + - /**/*.map + - /favicon.ico + - /actuator/** + - /druid/** + - /user/** + - /user/login + - /user/register + - /user/info + - /user/logout + - /minio/upload + mapper-locations: + - classpath:dao/*.xml + - classpath*:com/**/mapper/*.xml diff --git a/src/main/resources/mapper/UmsAdminRoleRelationMapper.xml b/src/main/resources/mapper/UmsAdminRoleRelationMapper.xml new file mode 100644 index 0000000..b09f07c --- /dev/null +++ b/src/main/resources/mapper/UmsAdminRoleRelationMapper.xml @@ -0,0 +1,44 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/mapper/UmsRoleMapper.xml b/src/main/resources/mapper/UmsRoleMapper.xml new file mode 100644 index 0000000..daaebc5 --- /dev/null +++ b/src/main/resources/mapper/UmsRoleMapper.xml @@ -0,0 +1,64 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +