|
|
- # AppletShiroRealm 触发问题分析
-
- ## 问题原因分析
-
- ### 1. 主要问题
- `AppletShiroRealm` 没有被触发的主要原因是:
-
- 1. **Shiro配置问题**: 在 `ShiroConfig.java` 中,`shiroFilter` 方法使用的是 `SecurityManager` 参数,但这个参数绑定的是 `securityManager` Bean,而不是 `appletSecurityManager`。
-
- 2. **过滤器配置问题**: 虽然配置了 `AppletJwtFilter`,但它没有正确关联到 `AppletShiroRealm`。
-
- 3. **用户服务接口问题**: `IAppletUserService` 的包路径发生了变化,导致依赖注入失败。
-
- ### 2. 具体问题点
-
- #### 2.1 Shiro配置问题
- ```java
- // 原来的配置
- @Bean("shiroFilterFactoryBean")
- public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
- // 这里使用的是 securityManager,而不是 appletSecurityManager
- }
- ```
-
- #### 2.2 过滤器链配置问题
- ```java
- // 小程序请求应该使用 appletApi 过滤器
- filterChainDefinitionMap.put("/appletApi/**", "appletApi");
- ```
-
- #### 2.3 用户服务依赖问题
- ```java
- // 原来的包路径
- import org.jeecg.modules.appletBackground.appletUser.service.IAppletUserService;
-
- // 修改后的包路径
- import org.jeecg.common.api.IAppletUserService;
- ```
-
- ## 解决方案
-
- ### 1. 修复Shiro配置
-
- #### 1.1 修改ShiroConfig.java
- - 在 `shiroFilter` 方法中添加小程序登录接口的匿名访问配置
- - 确保小程序请求使用正确的过滤器
-
- ```java
- // 小程序登录相关接口不需要认证
- filterChainDefinitionMap.put("/appletApi/login/wxLogin", "anon");
- filterChainDefinitionMap.put("/appletApi/login/getPhoneNumber", "anon");
-
- // applet专用过滤器,只处理/applet开头的请求
- filterChainDefinitionMap.put("/appletApi/**", "appletApi");
- ```
-
- #### 1.2 修复AppletJwtFilter
- - 添加登录接口的匿名访问检查
- - 完善token验证逻辑
- - 增加详细的错误日志
-
- ```java
- // 检查是否是登录相关接口,这些接口不需要认证
- if (requestPath.startsWith("/appletApi/login/wxLogin") ||
- requestPath.startsWith("/appletApi/login/getPhoneNumber")) {
- return true;
- }
- ```
-
- ### 2. 修复用户服务接口
-
- #### 2.1 创建统一的IAppletUserService接口
- ```java
- package org.jeecg.common.api;
-
- public interface IAppletUserService {
- AppletUser getByOpenid(String openid);
- AppletUser getByPhone(String phone);
- boolean save(AppletUser user);
- boolean updateById(AppletUser user);
- }
- ```
-
- #### 2.2 实现服务类
- ```java
- @Service
- public class AppletUserServiceImpl extends ServiceImpl<AppletUserMapper, AppletUser>
- implements IAppletUserService {
- // 实现具体方法
- }
- ```
-
- ### 3. 修复AppletShiroRealm
-
- #### 3.1 完善用户获取逻辑
- ```java
- private AppletUser getAppletUser(String openid) {
- try {
- // 从数据库查询用户信息
- AppletUser appletUser = appletUserService.getByOpenid(openid);
- if (appletUser != null) {
- log.debug("从数据库获取到小程序用户: {}", appletUser.getName());
- return appletUser;
- }
-
- log.warn("未找到小程序用户,openid: {}", openid);
- return null;
-
- } catch (Exception e) {
- log.error("获取小程序用户信息异常,openid: {}", openid, e);
- return null;
- }
- }
- ```
-
- #### 3.2 完善权限配置
- ```java
- @Override
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
- SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
-
- // 小程序用户默认权限
- info.addRole("applet_user");
- info.addStringPermission("applet:user:*");
-
- return info;
- }
- ```
-
- ### 4. 修复服务层方法
-
- #### 4.1 使用AppletUserUtil获取当前用户
- ```java
- public Result<String> bindPhoneNumber(String phoneCode) {
- try {
- // 获取当前登录用户
- AppletUser currentUser = AppletUserUtil.getCurrentAppletUser();
- if (currentUser == null) {
- return Result.error("用户未登录");
- }
-
- // 其他逻辑...
- } catch (Exception e) {
- log.error("绑定手机号异常", e);
- return Result.error("绑定失败: " + e.getMessage());
- }
- }
- ```
-
- #### 4.2 简化控制器方法
- ```java
- @GetMapping("/getUserInfo")
- public Result<AppletUser> getUserInfo() {
- log.info("收到获取用户信息请求");
- return appletApiLoginService.getUserInfo();
- }
- ```
-
- ## 测试验证
-
- ### 1. 创建测试控制器
- ```java
- @RestController
- @RequestMapping("/appletApi/test")
- public class AppletTestController {
-
- @GetMapping("/getCurrentUser")
- public Result<AppletUser> getCurrentUser() {
- AppletUser currentUser = AppletUserUtil.getCurrentAppletUser();
- if (currentUser == null) {
- return Result.error("用户未登录");
- }
- return Result.OK("获取成功", currentUser);
- }
- }
- ```
-
- ### 2. 测试步骤
- 1. 先调用登录接口获取token
- 2. 使用token调用测试接口
- 3. 检查日志中是否有 `AppletShiroRealm` 的调试信息
- 4. 验证用户信息是否正确返回
-
- ## 关键修复点总结
-
- ### 1. 配置层面
- - ✅ 修复了Shiro配置中的过滤器链
- - ✅ 添加了小程序登录接口的匿名访问
- - ✅ 确保小程序请求使用正确的过滤器
-
- ### 2. 代码层面
- - ✅ 修复了用户服务接口的包路径问题
- - ✅ 完善了AppletShiroRealm的用户获取逻辑
- - ✅ 添加了详细的日志记录
- - ✅ 使用AppletUserUtil简化用户获取
-
- ### 3. 测试层面
- - ✅ 创建了测试控制器验证功能
- - ✅ 提供了完整的测试步骤
-
- ## 预期效果
-
- 修复后,当访问 `/appletApi/**` 路径的请求时:
-
- 1. **AppletJwtFilter** 会被触发
- 2. **AppletShiroRealm** 会进行用户认证
- 3. **AppletUserUtil** 可以正确获取当前用户
- 4. 日志中会显示相关的调试信息
-
- ## 注意事项
-
- 1. **包路径**: 确保所有相关的import语句都使用正确的包路径
- 2. **Bean注入**: 确保 `IAppletUserService` 的实现类被正确注册为Spring Bean
- 3. **数据库**: 确保 `applet_user` 表存在且有数据
- 4. **Redis**: 确保Redis服务正常运行
- 5. **日志级别**: 建议将 `AppletShiroRealm` 的日志级别设置为DEBUG,便于调试
-
- ## 调试建议
-
- 1. 在 `AppletShiroRealm` 的关键方法中添加日志
- 2. 检查Spring Bean是否正确注入
- 3. 验证数据库连接和查询是否正常
- 4. 确认Redis缓存是否正常工作
- 5. 使用测试接口逐步验证功能
|