1.【修复】定时任务刷新本地缓存时,无租户上线文,导致查询报错

2. member 模块,统一使用 member 前缀
3. 修改 Spring Security logout 配置,支持多用户类型的退出
This commit is contained in:
YunaiV 2022-01-29 14:05:06 +08:00
parent 6aca4ae9fd
commit cee7e50720
18 changed files with 63 additions and 55 deletions

View File

@ -1,7 +1,6 @@
{ {
"local": { "local": {
"baseUrl": "http://127.0.0.1:48080/api", "baseUrl": "http://127.0.0.1:48080/api",
"userServerUrl": "http://127.0.0.1:28080/api",
"token": "test1", "token": "test1",
"userApi": "http://127.0.0.1:48080/app-api", "userApi": "http://127.0.0.1:48080/app-api",

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptListReqVO; import cn.iocoder.yudao.adminserver.modules.system.controller.dept.vo.dept.SysDeptListReqVO;
import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dept.SysDeptDO; import cn.iocoder.yudao.coreservice.modules.system.dal.dataobject.dept.SysDeptDO;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.apache.ibatis.annotations.Mapper; import org.apache.ibatis.annotations.Mapper;
@ -28,6 +29,7 @@ public interface SysDeptMapper extends BaseMapperX<SysDeptDO> {
return selectCount(SysDeptDO::getParentId, parentId); return selectCount(SysDeptDO::getParentId, parentId);
} }
@InterceptorIgnore(tenantLine = "on") // 该方法忽略多租户原因该方法被异步 task 调用此时获取不到租户编号
default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) { default boolean selectExistsByUpdateTimeAfter(Date maxUpdateTime) {
return selectOne(new LambdaQueryWrapper<SysDeptDO>().select(SysDeptDO::getId) return selectOne(new LambdaQueryWrapper<SysDeptDO>().select(SysDeptDO::getId)
.gt(SysDeptDO::getUpdateTime, maxUpdateTime).last(SqlConstants.LIMIT1)) != null; .gt(SysDeptDO::getUpdateTime, maxUpdateTime).last(SqlConstants.LIMIT1)) != null;

View File

@ -1,5 +1,6 @@
package cn.iocoder.yudao.framework.security.config; package cn.iocoder.yudao.framework.security.config;
import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider; import cn.iocoder.yudao.framework.security.core.authentication.MultiUserDetailsAuthenticationProvider;
import cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter; import cn.iocoder.yudao.framework.security.core.filter.JWTAuthenticationTokenFilter;
import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService; import cn.iocoder.yudao.framework.security.core.service.SecurityAuthFrameworkService;
@ -21,8 +22,10 @@ import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.access.AccessDeniedHandler; import org.springframework.security.web.access.AccessDeniedHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter; import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler; import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.security.web.util.matcher.RequestMatcher;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
/** /**
* 自定义的 Spring Security 配置适配器实现 * 自定义的 Spring Security 配置适配器实现
@ -106,6 +109,7 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
*/ */
@Override @Override
protected void configure(HttpSecurity httpSecurity) throws Exception { protected void configure(HttpSecurity httpSecurity) throws Exception {
// 登出
httpSecurity httpSecurity
// 开启跨域 // 开启跨域
.cors().and() .cors().and()
@ -117,7 +121,9 @@ public class YudaoWebSecurityConfigurerAdapter extends WebSecurityConfigurerAdap
// 一堆自定义的 Spring Security 处理器 // 一堆自定义的 Spring Security 处理器
.exceptionHandling().authenticationEntryPoint(authenticationEntryPoint) .exceptionHandling().authenticationEntryPoint(authenticationEntryPoint)
.accessDeniedHandler(accessDeniedHandler).and() .accessDeniedHandler(accessDeniedHandler).and()
.logout().logoutUrl(buildAdminApi("/logout")).logoutSuccessHandler(logoutSuccessHandler); // 登出 // 登出地址的配置
.logout().logoutSuccessHandler(logoutSuccessHandler).logoutRequestMatcher(request -> // 匹配多种用户类型的登出
StrUtil.equalsAny(request.getRequestURI(), buildAdminApi("/logout"), buildAppApi("/member/logout")));
// 设置每个请求的权限 全局共享规则 // 设置每个请求的权限 全局共享规则
httpSecurity.authorizeRequests() httpSecurity.authorizeRequests()

View File

@ -41,6 +41,19 @@ public class SecurityFrameworkUtils {
return authorization.substring(index + 7).trim(); return authorization.substring(index + 7).trim();
} }
/**
* 获得当前认证信息
*
* @return 认证信息
*/
public static Authentication getAuthentication() {
SecurityContext context = SecurityContextHolder.getContext();
if (context == null) {
return null;
}
return context.getAuthentication();
}
/** /**
* 获取当前用户 * 获取当前用户
* *
@ -48,11 +61,7 @@ public class SecurityFrameworkUtils {
*/ */
@Nullable @Nullable
public static LoginUser getLoginUser() { public static LoginUser getLoginUser() {
SecurityContext context = SecurityContextHolder.getContext(); Authentication authentication = getAuthentication();
if (context == null) {
return null;
}
Authentication authentication = context.getAuthentication();
if (authentication == null) { if (authentication == null) {
return null; return null;
} }
@ -88,16 +97,22 @@ public class SecurityFrameworkUtils {
* @param request 请求 * @param request 请求
*/ */
public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) { public static void setLoginUser(LoginUser loginUser, HttpServletRequest request) {
// 创建 UsernamePasswordAuthenticationToken 对象 // 创建 Authentication并设置到上下文
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken( Authentication authentication = buildAuthentication(loginUser, request);
loginUser, null, loginUser.getAuthorities()); SecurityContextHolder.getContext().setAuthentication(authentication);
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
// 设置到上下文
SecurityContextHolder.getContext().setAuthentication(authenticationToken);
// 额外设置到 request 用于 ApiAccessLogFilter 可以获取到用户编号 // 额外设置到 request 用于 ApiAccessLogFilter 可以获取到用户编号
// 原因是Spring Security Filter ApiAccessLogFilter 后面在它记录访问日志时线上上下文已经没有用户编号等信息 // 原因是Spring Security Filter ApiAccessLogFilter 后面在它记录访问日志时线上上下文已经没有用户编号等信息
WebFrameworkUtils.setLoginUserId(request, loginUser.getId()); WebFrameworkUtils.setLoginUserId(request, loginUser.getId());
WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType()); WebFrameworkUtils.setLoginUserType(request, loginUser.getUserType());
} }
private static Authentication buildAuthentication(LoginUser loginUser, HttpServletRequest request) {
// 创建 UsernamePasswordAuthenticationToken 对象
UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(
loginUser, null, loginUser.getAuthorities());
authenticationToken.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));
return authenticationToken;
}
} }

View File

@ -10,17 +10,11 @@ import cn.iocoder.yudao.coreservice.modules.bpm.api.group.BpmUserGroupServiceApi
import cn.iocoder.yudao.coreservice.modules.system.service.dept.SysDeptCoreService; import cn.iocoder.yudao.coreservice.modules.system.service.dept.SysDeptCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.permission.SysPermissionCoreService; import cn.iocoder.yudao.coreservice.modules.system.service.permission.SysPermissionCoreService;
import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService; import cn.iocoder.yudao.coreservice.modules.system.service.user.SysUserCoreService;
import cn.iocoder.yudao.adminserver.modules.bpm.service.definition.BpmUserGroupService;
import cn.iocoder.yudao.adminserver.modules.system.service.dept.SysDeptService;
import cn.iocoder.yudao.adminserver.modules.system.service.permission.SysPermissionService;
import cn.iocoder.yudao.adminserver.modules.system.service.user.SysUserService;
import org.activiti.api.runtime.shared.identity.UserGroupManager; import org.activiti.api.runtime.shared.identity.UserGroupManager;
import org.activiti.core.common.spring.identity.ActivitiUserGroupManagerImpl;
import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer; import org.activiti.spring.boot.ProcessEngineConfigurationConfigurer;
import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.core.userdetails.UserDetailsService;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;

View File

@ -1,5 +1,5 @@
### 请求 /login 接口 => 成功 ### 请求 /login 接口 => 成功
POST {{userApi}}/login POST {{userApi}}/member/login
Content-Type: application/json Content-Type: application/json
tenant-id: {{userTenentId}} tenant-id: {{userTenentId}}
@ -9,8 +9,9 @@ tenant-id: {{userTenentId}}
} }
### 请求 /send-sms-code 接口 => 成功 ### 请求 /send-sms-code 接口 => 成功
POST {{userServerUrl}}/send-sms-code POST {{userApi}}/member/send-sms-code
Content-Type: application/json Content-Type: application/json
tenant-id: {{userTenentId}}
{ {
"mobile": "15601691399", "mobile": "15601691399",
@ -18,8 +19,9 @@ Content-Type: application/json
} }
### 请求 /sms-login 接口 => 成功 ### 请求 /sms-login 接口 => 成功
POST {{userServerUrl}}/sms-login POST {{userApi}}/member/sms-login
Content-Type: application/json Content-Type: application/json
tenant-id: {{userTenentId}}
{ {
"mobile": "15601691301", "mobile": "15601691301",
@ -27,6 +29,7 @@ Content-Type: application/json
} }
### 请求 /logout 接口 => 成功 ### 请求 /logout 接口 => 成功
POST {{userServerUrl}}/logout POST {{userApi}}/member/logout
Content-Type: application/json Content-Type: application/json
Authorization: Bearer c1b76bdaf2c146c581caa4d7fd81ee66 Authorization: Bearer c1b76bdaf2c146c581caa4d7fd81ee66
tenant-id: {{userTenentId}}

View File

@ -5,6 +5,7 @@ import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog;
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated; import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils;
import cn.iocoder.yudao.module.member.controller.app.auth.vo.*; import cn.iocoder.yudao.module.member.controller.app.auth.vo.*;
import cn.iocoder.yudao.module.member.service.auth.AuthService; import cn.iocoder.yudao.module.member.service.auth.AuthService;
import cn.iocoder.yudao.module.member.service.sms.SysSmsCodeService; import cn.iocoder.yudao.module.member.service.sms.SysSmsCodeService;
@ -13,6 +14,7 @@ import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation; import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
@ -26,7 +28,7 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti
@Api(tags = "APP 端 - 认证") @Api(tags = "APP 端 - 认证")
@RestController @RestController
@RequestMapping("/") @RequestMapping("/member/")
@Validated @Validated
@Slf4j @Slf4j
public class AppAuthController { public class AppAuthController {
@ -39,6 +41,9 @@ public class AppAuthController {
@Resource @Resource
private SysSocialCoreService socialService; private SysSocialCoreService socialService;
@Resource
private LogoutSuccessHandler logoutSuccessHandler;
@PostMapping("/login") @PostMapping("/login")
@ApiOperation("使用手机 + 密码登录") @ApiOperation("使用手机 + 密码登录")
@OperateLog(enable = false) // 避免 Post 请求被记录操作日志 @OperateLog(enable = false) // 避免 Post 请求被记录操作日志

View File

@ -1,4 +1,4 @@
package cn.iocoder.yudao.userserver.modules.weixin.controller.mp; package cn.iocoder.yudao.module.member.controller.app.weixin;
import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import io.swagger.annotations.Api; import io.swagger.annotations.Api;
@ -19,10 +19,10 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Api(tags = "微信公众号") @Api(tags = "微信公众号")
@RestController @RestController
@RequestMapping("/wx/mp") @RequestMapping("/member/wx-mp")
@Validated @Validated
@Slf4j @Slf4j
public class WxMpController { public class AppWxMpController {
@Resource @Resource
private WxMpService mpService; private WxMpService mpService;

View File

@ -16,7 +16,7 @@ import java.util.Date;
* *
* @author 芋道源码 * @author 芋道源码
*/ */
@TableName(value = "mbr_user", autoResultMap = true) @TableName(value = "member_user", autoResultMap = true)
@Data @Data
@EqualsAndHashCode(callSuper = true) @EqualsAndHashCode(callSuper = true)
@Builder @Builder

View File

@ -4,6 +4,6 @@
* 2. redisRedis CRUD 操作 * 2. redisRedis CRUD 操作
* 3. mysqlMySQL CRUD 操作 * 3. mysqlMySQL CRUD 操作
* *
* 其中MySQL 的表以 mbr_ 作为前缀 * 其中MySQL 的表以 member_ 作为前缀
*/ */
package cn.iocoder.yudao.module.member.dal; package cn.iocoder.yudao.module.member.dal;

View File

@ -1 +1,8 @@
/**
* member 模块我们放会员业务
* 例如说会员中心等等
*
* 1. Controller URL /member/ 开头避免和其它 Module 冲突
* 2. DataObject 表名 member_ 开头方便在数据库中区分
*/
package cn.iocoder.yudao.module.member; package cn.iocoder.yudao.module.member;

View File

@ -1,2 +1,2 @@
-- mbr 开头的 DB -- mbr 开头的 DB
DELETE FROM "mbr_user"; DELETE FROM "member_user";

View File

@ -1,5 +1,5 @@
-- mbr 开头的 DB -- mbr 开头的 DB
CREATE TABLE IF NOT EXISTS "mbr_user" ( CREATE TABLE IF NOT EXISTS "member_user" (
"id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '编号', "id" bigint NOT NULL GENERATED BY DEFAULT AS IDENTITY COMMENT '编号',
"nickname" varchar(30) NOT NULL DEFAULT '' COMMENT '用户昵称', "nickname" varchar(30) NOT NULL DEFAULT '' COMMENT '用户昵称',
"avatar" varchar(255) NOT NULL DEFAULT '' COMMENT '头像', "avatar" varchar(255) NOT NULL DEFAULT '' COMMENT '头像',

View File

@ -1,14 +0,0 @@
package cn.iocoder.yudao.userserver;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SuppressWarnings("SpringComponentScan") // 忽略 IDEA 无法识别 ${yudao.info.base-package} ${yudao.core-service.base-package}
@SpringBootApplication(scanBasePackages = {"${yudao.info.base-package}", "${yudao.core-service.base-package}"})
public class UserServerApplication {
public static void main(String[] args) {
SpringApplication.run(UserServerApplication.class, args);
}
}

View File

@ -1,7 +0,0 @@
/**
* weixin 包下我们放通用业务支撑上层的核心业务
* 例如说用户部门权限数据字典等等
*
* 缩写wx
*/
package cn.iocoder.yudao.userserver.modules.weixin;

View File

@ -37,8 +37,6 @@ mybatis-plus:
mapper-locations: classpath*:mapper/*.xml mapper-locations: classpath*:mapper/*.xml
type-aliases-package: ${yudao.info.base-package}.modules.*.dal.dataobject, ${yudao.core-service.base-package}.modules.*.dal.dataobject type-aliases-package: ${yudao.info.base-package}.modules.*.dal.dataobject, ${yudao.core-service.base-package}.modules.*.dal.dataobject
--- #################### 芋道相关配置 #################### --- #################### 芋道相关配置 ####################
yudao: yudao:
@ -67,5 +65,4 @@ yudao:
- cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConstants - cn.iocoder.yudao.userserver.modules.member.enums.MbrErrorCodeConstants
- cn.iocoder.yudao.userserver.modules.system.enums.SysErrorCodeConstants - cn.iocoder.yudao.userserver.modules.system.enums.SysErrorCodeConstants
debug: false debug: false

View File

@ -23,6 +23,7 @@
### 🐞 Bug Fixes ### 🐞 Bug Fixes
*【修复】用户无权限访问 指定 API 时,未返回 FORBIDDEN 结果码 *【修复】用户无权限访问 指定 API 时,未返回 FORBIDDEN 结果码
*【修复】定时任务刷新本地缓存时,无租户上线文,导致查询报错
### 🔨 Dependency Upgrades ### 🔨 Dependency Upgrades