diff --git a/tamguo-oms/src/main/java/com/tamguo/config/WebConfig.java b/tamguo-oms/src/main/java/com/tamguo/config/WebConfig.java index 30ee016..79181a4 100644 --- a/tamguo-oms/src/main/java/com/tamguo/config/WebConfig.java +++ b/tamguo-oms/src/main/java/com/tamguo/config/WebConfig.java @@ -9,22 +9,39 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import com.tamguo.modules.sys.interceptor.SettingsInterceptor; +// 表明这是一个Spring的配置类,Spring会扫描这个类并处理其中实现了WebMvcConfigurer接口的方法,用于对Spring Web相关功能进行配置,比如添加拦截器、配置资源处理器等。 @Configuration public class WebConfig implements WebMvcConfigurer { - + + // 使用@Value注解从配置文件(通常是application.properties或application.yml等)中读取名为"file.storage.path"的配置项的值,并注入到fileStoragePath变量中, + // 该变量用于存储文件存储的路径信息,后续在配置资源处理器时会用到这个路径来指定静态资源的实际存放位置。 @Value("${file.storage.path}") private String fileStoragePath; + + // 通过@Autowired注解自动注入SettingsInterceptor实例,SettingsInterceptor应该是自定义的拦截器类, + // 用于在请求处理过程中进行一些通用的业务逻辑处理,比如权限验证、设置一些通用的请求参数等,具体功能取决于该拦截器类的实现逻辑。 @Autowired private SettingsInterceptor settingsInterceptor; - + + /** + * 重写WebMvcConfigurer接口的addInterceptors方法,用于向Spring Web的拦截器注册表中添加自定义的拦截器。 + * 在这里将之前注入的SettingsInterceptor添加到拦截器注册表中,并设置其拦截的路径模式为"/**",意味着所有的请求都会经过这个拦截器进行处理。 + * 这样可以在拦截器的具体实现中对请求进行统一的前置或后置处理,例如检查用户权限、记录请求日志等操作。 + */ @Override public void addInterceptors(InterceptorRegistry registry) { registry.addInterceptor(settingsInterceptor).addPathPatterns("/**"); } - - @Override - public void addResourceHandlers(ResourceHandlerRegistry registry) { - registry.addResourceHandler("/files/**").addResourceLocations("file:"+fileStoragePath); - } - -} + + /** + * 重写WebMvcConfigurer接口的addResourceHandlers方法,用于配置Spring Web的资源处理器,使得应用能够正确处理和访问特定路径下的静态资源。 + * 在这里配置了对"/files/**"路径下的资源请求的处理方式,通过addResourceLocations方法指定了这些资源实际所在的位置, + * 格式为"file:" + fileStoragePath,表示资源位于文件系统中,具体路径由fileStoragePath变量所指定的值来确定, + * 例如可以将项目中的图片、文档等静态文件存放在这个指定路径下,然后通过"/files/"开头的URL路径来访问这些资源。 + */ + @Override + public void addResourceHandlers(ResourceHandlerRegistry registry) { + registry.addResourceHandler("/files/**").addResourceLocations("file:" + fileStoragePath); + } + +} \ No newline at end of file diff --git a/tamguo-oms/src/main/java/com/tamguo/config/dao/MyMetaObjectHandler.java b/tamguo-oms/src/main/java/com/tamguo/config/dao/MyMetaObjectHandler.java index d0c8b11..fc2ef86 100644 --- a/tamguo-oms/src/main/java/com/tamguo/config/dao/MyMetaObjectHandler.java +++ b/tamguo-oms/src/main/java/com/tamguo/config/dao/MyMetaObjectHandler.java @@ -10,24 +10,43 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** - * 注入公共字段自动填充,任选注入方式即可 + * 此类用于注入公共字段自动填充功能,它继承自MyBatis Plus的MetaObjectHandler类。 + * 可以根据实际情况选择这种注入方式来实现自动填充公共字段的需求。 + * 注意,当前类被注释掉的@Component注解表明它原本可能是想作为Spring的组件被管理,以便能在项目中自动生效,但可能由于某些配置原因等暂未启用这种方式,任选注入方式即可表示可能还有其他等价的实现方式来达到同样的自动填充效果。 */ //@Component public class MyMetaObjectHandler extends MetaObjectHandler { + // 创建一个名为logger的静态常量,用于记录日志,LoggerFactory根据当前类的类型(MyMetaObjectHandler.class)创建对应的Logger实例,方便后续在代码中输出相关的日志信息。 protected final static Logger logger = LoggerFactory.getLogger(MyMetaObjectHandler.class); - + + /** + * 重写父类的insertFill方法,此方法会在执行插入操作(比如插入数据到数据库表)时被调用,用于自动填充一些公共字段的值。 + * + * @param metaObject MyBatis的MetaObject对象,通过它可以获取和设置对象的属性值等相关操作,在这里就是利用它来为要插入的实体对象设置相应的公共字段值。 + */ @Override public void insertFill(MetaObject metaObject) { - setFieldValByName("createBy", ShiroUtils.getUserCode() , metaObject); - setFieldValByName("updateBy", ShiroUtils.getUserCode() , metaObject); - setFieldValByName("createDate", new Date() , metaObject); - setFieldValByName("updateDate", new Date() , metaObject); + // 使用MyBatis Plus提供的方法setFieldValByName,通过字段名"createBy",将值(从ShiroUtils.getUserCode()获取,可能是获取当前用户的代码等标识信息)设置到metaObject所对应的实体对象中,实现自动填充创建者字段的功能。 + setFieldValByName("createBy", ShiroUtils.getUserCode(), metaObject); + // 同样的方式,为更新者字段"updateBy"也设置为当前用户的代码,因为在插入时,创建者和首次更新者可能是同一个人,具体可根据业务逻辑调整。 + setFieldValByName("updateBy", ShiroUtils.getUserCode(), metaObject); + // 通过字段名"createDate",将当前的日期时间(new Date()获取当前系统时间)设置到实体对象中,自动填充创建时间字段。 + setFieldValByName("createDate", new Date(), metaObject); + // 为更新时间字段"updateDate"也设置为当前系统时间,插入操作时可以认为首次更新时间就是创建时间,后续更新操作会再次触发更新时间的更新逻辑。 + setFieldValByName("updateDate", new Date(), metaObject); } + /** + * 重写父类的updateFill方法,此方法会在执行更新操作(比如更新数据库表中的数据)时被调用,用于自动填充更新相关的公共字段的值。 + * + * @param metaObject MyBatis的MetaObject对象,用于操作要更新的实体对象的属性值设置等,在这里就是利用它来为实体对象设置更新相关的公共字段值。 + */ @Override public void updateFill(MetaObject metaObject) { - setFieldValByName("updateBy", ShiroUtils.getUserCode() , metaObject); - setFieldValByName("updateDate", new Date() , metaObject); + // 使用setFieldValByName方法,通过字段名"updateBy",将值(从ShiroUtils.getUserCode()获取当前用户代码)设置到metaObject对应的实体对象中,自动填充更新者字段,确保记录更新操作是谁执行的。 + setFieldValByName("updateBy", ShiroUtils.getUserCode(), metaObject); + // 通过字段名"updateDate",将当前系统时间(new Date()获取)设置到实体对象中,自动更新更新时间字段,保证更新时间的准确性。 + setFieldValByName("updateDate", new Date(), metaObject); } -} +} \ No newline at end of file diff --git a/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionConfig.java b/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionConfig.java index c2376a1..2550735 100644 --- a/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionConfig.java +++ b/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionConfig.java @@ -5,24 +5,36 @@ import org.springframework.context.annotation.Bean; import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.session.data.redis.config.annotation.web.http.EnableRedisHttpSession; -//这个类用配置redis服务器的连接 -@EnableRedisHttpSession(maxInactiveIntervalInSeconds= 1800) +// 这个类用于配置redis服务器的连接,通过该类可以设置与Redis服务器建立连接所需的各项参数,如主机名、端口、密码等,并创建对应的Jedis连接工厂对象。 +@EnableRedisHttpSession(maxInactiveIntervalInSeconds = 1800) +// @EnableRedisHttpSession注解用于启用Spring Session基于Redis的HTTP会话管理功能。 +// maxInactiveIntervalInSeconds属性设置了会话的最大非活动时间间隔,这里设置为1800秒,即30分钟,表示如果一个会话在30分钟内没有任何活动,将会被视为过期并失效。 public class SessionConfig { + // 使用@Value注解从配置文件(通常是application.properties或application.yml等)中读取名为"redis.hostname"的配置项的值,并注入到HostName变量中,该变量用于存储Redis服务器的主机名。 @Value("${redis.hostname}") String HostName; + + // 同样通过@Value注解从配置文件中读取"redis.port"配置项的值,注入到Port变量中,用于存储Redis服务器的端口号。 @Value("${redis.port}") int Port; + + // 从配置文件读取"redis.password"配置项的值,注入到password变量中,用于存储连接Redis服务器所需的密码(如果有的话)。 @Value("${redis.password}") String password; + // @SuppressWarnings("deprecation")注解用于抑制编译器对于使用已过时方法或类等情况的警告提示。 + // 这里定义了一个名为connectionFactory的方法,并使用@Bean注解将该方法返回的对象注册为Spring容器中的一个Bean,该Bean就是Jedis连接工厂对象,用于创建与Redis服务器的连接。 @SuppressWarnings("deprecation") @Bean public JedisConnectionFactory connectionFactory() { JedisConnectionFactory connection = new JedisConnectionFactory(); + // 设置Jedis连接工厂对象的端口号,使用之前从配置文件中读取并注入的Port变量来指定具体的端口值。 connection.setPort(Port); + // 设置Jedis连接工厂对象的主机名,使用HostName变量来指定连接的Redis服务器的主机名称。 connection.setHostName(HostName); + // 设置Jedis连接工厂对象的密码,通过password变量来传入连接Redis服务器所需的密码,确保连接的安全性(如果有密码要求的话)。 connection.setPassword(password); return connection; } -} +} \ No newline at end of file diff --git a/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionInitializer.java b/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionInitializer.java index 3477712..59d5979 100644 --- a/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionInitializer.java +++ b/tamguo-oms/src/main/java/com/tamguo/config/redis/SessionInitializer.java @@ -2,9 +2,15 @@ package com.tamguo.config.redis; import org.springframework.session.web.context.AbstractHttpSessionApplicationInitializer; -//初始化Session配置 -public class SessionInitializer extends AbstractHttpSessionApplicationInitializer{ +// 这个类用于初始化Session配置,它继承自Spring框架提供的AbstractHttpSessionApplicationInitializer类, +// 通过继承该抽象类并实现相应的构造函数等逻辑,来协助完成与Http Session相关配置的初始化工作,确保Session相关功能能够正常启用和配置生效。 +public class SessionInitializer extends AbstractHttpSessionApplicationInitializer { + + // 定义构造函数,在创建SessionInitializer类的实例时会调用该构造函数。 + // 这里调用父类(AbstractHttpSessionApplicationInitializer)的构造函数,并传入SessionConfig.class作为参数。 + // 其目的是告知Spring框架要使用SessionConfig这个配置类来初始化Http Session相关的配置, + // 使得在整个应用启动过程中,基于之前在SessionConfig类中定义的如Redis连接等相关配置能够正确地应用到Http Session的管理中,从而保证Session功能的正常运行。 public SessionInitializer() { super(SessionConfig.class); } -} +} \ No newline at end of file diff --git a/tamguo-oms/src/main/java/com/tamguo/config/shiro/ShiroConfiguration.java b/tamguo-oms/src/main/java/com/tamguo/config/shiro/ShiroConfiguration.java index b26913f..fecf3d6 100644 --- a/tamguo-oms/src/main/java/com/tamguo/config/shiro/ShiroConfiguration.java +++ b/tamguo-oms/src/main/java/com/tamguo/config/shiro/ShiroConfiguration.java @@ -11,15 +11,24 @@ import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreato import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; +// 表明这是一个Spring的配置类,Spring会扫描这个类并处理其中带有@Bean注解的方法,将这些方法返回的对象注册为Spring容器中的Bean,用于配置Shiro相关的功能组件。 @Configuration public class ShiroConfiguration { + + // 创建一个静态的LinkedHashMap,用于存储Shiro的过滤链定义。LinkedHashMap可以保证元素的插入顺序,便于按照定义顺序来匹配过滤规则。 + // 键为请求的URL路径模式,值为对应的访问控制规则(如"anon"表示匿名可访问,"authc"表示需要认证后才能访问等)。 private static Map filterChainDefinitionMap = new LinkedHashMap(); + // 定义一个名为"shiroRealm"的Bean,该Bean返回一个UserRealm实例。UserRealm通常是自定义的实现了Shiro的Realm接口的类, + // 用于从数据源(如数据库)中获取用户认证和授权相关的信息,是Shiro进行身份验证和权限验证的核心逻辑所在。 @Bean(name = "shiroRealm") public UserRealm getShiroRealm() { return new UserRealm(); } + // 定义一个名为"shiroEhcacheManager"的Bean,用于创建并配置EhCacheManager实例。EhCacheManager是Shiro用于缓存的管理器, + // 在这里通过设置缓存配置文件(classpath:ehcache-shiro.xml)来指定缓存的相关配置信息,比如缓存的存活时间、缓存区域划分等, + // 以提高Shiro在处理认证和授权过程中的性能,避免频繁地从数据源获取相同的数据。 @Bean(name = "shiroEhcacheManager") public EhCacheManager getEhCacheManager() { EhCacheManager em = new EhCacheManager(); @@ -27,11 +36,17 @@ public class ShiroConfiguration { return em; } + // 定义一个名为"lifecycleBeanPostProcessor"的Bean,创建并返回一个LifecycleBeanPostProcessor实例。 + // LifecycleBeanPostProcessor是Shiro提供的一个用于管理Shiro相关Bean生命周期的后置处理器, + // 它能确保Shiro的各种组件(如Realm、SecurityManager等)在Spring容器中的生命周期方法(如初始化、销毁等)得到正确调用。 @Bean(name = "lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor getLifecycleBeanPostProcessor() { return new LifecycleBeanPostProcessor(); } + // 定义一个名为"defaultAdvisorAutoProxyCreator"的Bean,创建并配置DefaultAdvisorAutoProxyCreator实例。 + // 它是Spring AOP中的一个自动代理创建器,用于根据Advisor(通知器,包含了切点和增强逻辑)来自动创建代理对象, + // 设置proxyTargetClass为true表示使用基于类的代理方式(而不是基于接口的代理),这样可以确保Shiro的安全切面等逻辑能够正确应用到目标对象上。 @Bean public DefaultAdvisorAutoProxyCreator getDefaultAdvisorAutoProxyCreator() { DefaultAdvisorAutoProxyCreator daap = new DefaultAdvisorAutoProxyCreator(); @@ -39,6 +54,9 @@ public class ShiroConfiguration { return daap; } + // 定义一个名为"securityManager"的Bean,创建并返回一个DefaultWebSecurityManager实例,它是Shiro在Web环境下的核心安全管理器。 + // 在这里配置了它所使用的Realm(通过调用getShiroRealm()方法获取自定义的UserRealm实例)以及缓存管理器(通过调用getEhCacheManager()方法获取EhCacheManager实例), + // 负责协调Shiro的各个组件,如认证、授权、会话管理等功能的执行,是整个Shiro安全框架在应用中的核心控制组件。 @Bean(name = "securityManager") public DefaultWebSecurityManager getDefaultWebSecurityManager() { DefaultWebSecurityManager dwsm = new DefaultWebSecurityManager(); @@ -47,19 +65,30 @@ public class ShiroConfiguration { return dwsm; } + // 定义一个名为"authorizationAttributeSourceAdvisor"的Bean,创建并返回一个AuthorizationAttributeSourceAdvisor实例。 + // 它是Shiro与Spring AOP结合的一个通知器,用于在方法级别进行权限控制,通过设置安全管理器(调用getDefaultWebSecurityManager()方法获取), + // 可以基于方法上的权限注解(如@RequiresPermissions等)来自动进行权限验证,实现细粒度的访问控制。 @Bean public AuthorizationAttributeSourceAdvisor getAuthorizationAttributeSourceAdvisor() { AuthorizationAttributeSourceAdvisor aasa = new AuthorizationAttributeSourceAdvisor(); aasa.setSecurityManager(getDefaultWebSecurityManager()); return new AuthorizationAttributeSourceAdvisor(); } - + + // 定义一个名为"shiroFilter"的Bean,创建并返回一个ShiroFilterFactoryBean实例,它是Shiro在Web应用中用于配置过滤链的核心组件。 + // 首先设置了安全管理器(通过调用getDefaultWebSecurityManager()方法获取),确定了整个过滤链的安全控制基础。 + // 然后设置了登录页面的URL("/login"),即当用户未认证访问受保护资源时,会被重定向到该登录页面进行认证操作。 + // 接着设置了认证成功后的跳转页面URL("/index"),用于用户成功登录后自动跳转到相应的页面。 + // 之后通过往filterChainDefinitionMap中添加一系列的URL路径模式和对应的访问控制规则,来定义哪些资源是匿名可访问(如各种前端框架相关的静态资源路径),哪些资源需要认证访问("/**"表示除了前面配置的匿名可访问路径外的其他所有路径)。 + // 最后将配置好的过滤链定义Map设置到ShiroFilterFactoryBean中,使其生效,从而实现整个Web应用基于Shiro的访问控制。 @Bean(name = "shiroFilter") public ShiroFilterFactoryBean getShiroFilterFactoryBean() { ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean(); shiroFilterFactoryBean.setSecurityManager(getDefaultWebSecurityManager()); shiroFilterFactoryBean.setLoginUrl("/login"); shiroFilterFactoryBean.setSuccessUrl("/index"); + + // 以下是配置各种静态资源路径为匿名可访问,这些资源通常是前端框架的相关文件,不需要进行认证就能访问,方便页面正常加载和展示。 filterChainDefinitionMap.put("/jquery/**", "anon"); filterChainDefinitionMap.put("/adminlte/**", "anon"); filterChainDefinitionMap.put("/bootstrap/**", "anon"); @@ -86,11 +115,12 @@ public class ShiroConfiguration { filterChainDefinitionMap.put("/jquery-timeago/**", "anon"); filterChainDefinitionMap.put("/favicon.ico", "anon"); filterChainDefinitionMap.put("/global.min.js", "anon"); - - + + // 将除了上述配置的匿名可访问路径之外的所有请求路径都设置为需要认证访问("authc"表示需要认证),实现了对整个Web应用的基本访问控制。 filterChainDefinitionMap.put("/**", "authc"); + shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap); + return shiroFilterFactoryBean; } - } \ No newline at end of file diff --git a/tamguo-oms/src/main/java/com/tamguo/config/shiro/UserRealm.java b/tamguo-oms/src/main/java/com/tamguo/config/shiro/UserRealm.java index 5b26aa1..6441e87 100644 --- a/tamguo-oms/src/main/java/com/tamguo/config/shiro/UserRealm.java +++ b/tamguo-oms/src/main/java/com/tamguo/config/shiro/UserRealm.java @@ -17,55 +17,66 @@ import com.tamguo.modules.sys.model.enums.SysUserStatusEnum; import com.tamguo.modules.sys.service.ISysUserService; /** - * 认证 - * + * 这个类 `UserRealm` 继承自 `AuthorizingRealm`,是Shiro框架中用于实现认证和授权逻辑的核心类。 + * 它负责与业务层的用户服务进行交互,完成用户登录认证以及权限验证相关的操作,是整个应用基于Shiro进行安全控制的关键部分。 + * */ public class UserRealm extends AuthorizingRealm { - + + // 通过Spring的依赖注入(@Autowired注解),自动注入 `ISysUserService` 接口的实现类实例, + // 用于后续从业务层获取用户相关信息,比如根据用户名查询用户实体对象等操作,实现与业务逻辑层的交互,以完成认证和授权的具体业务判断。 @Autowired private ISysUserService sysUserService; - + /** * 授权(验证权限时调用) + * 此方法是Shiro框架要求必须实现的用于获取授权信息的方法。当需要验证用户是否具有某个权限时(例如访问受权限控制的资源),Shiro会调用该方法来获取用户的权限信息。 + * 目前该方法中只是创建了一个空的 `SimpleAuthorizationInfo` 对象返回,实际应用中通常需要根据业务逻辑从数据库等数据源获取用户对应的权限信息,并设置到 `info` 对象中返回给Shiro框架进行权限判断。 */ - @Override - protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { - SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); - // info.setStringPermissions(permsSet); - - return info; - } + @Override + protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { + SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); + // info.setStringPermissions(permsSet); // 此处可能原本计划设置用户的权限集合,但目前未实现具体逻辑,可能需要根据实际业务从数据库查询用户权限并设置进来 + + return info; + } - /** - * 认证(登录时调用) - */ - @Override - protected AuthenticationInfo doGetAuthenticationInfo( - AuthenticationToken token) throws AuthenticationException { - String username = (String) token.getPrincipal(); + /** + * 认证(登录时调用) + * 此方法是Shiro框架用于进行用户登录认证的核心方法。当用户发起登录请求时,Shiro会调用该方法来验证用户输入的账号(用户名)和密码是否正确,以及账号状态是否正常等情况。 + */ + @Override + protected AuthenticationInfo doGetAuthenticationInfo( + AuthenticationToken token) throws AuthenticationException { + // 从传入的 `AuthenticationToken` 对象中获取用户名(通常作为登录的标识),这里将其强制转换为 `String` 类型,因为在实际应用中一般用户名是以字符串形式存在的。 + String username = (String) token.getPrincipal(); + // 从 `AuthenticationToken` 对象中获取用户输入的密码,并将其从字符数组转换为 `String` 类型,以便后续与数据库中存储的密码进行比对。 String password = new String((char[]) token.getCredentials()); - - //查询用户信息 + + // 通过注入的 `ISysUserService` 实例,调用其 `queryByLoginCode` 方法,根据用户名去查询对应的用户信息,该方法会与业务层的数据访问层交互,从数据库中获取用户实体对象(如果存在的话)。 SysUserEntity user = sysUserService.queryByLoginCode(username); - - //账号不存在 - if(user == null) { + + // 如果查询到的用户对象为 `null`,说明输入的用户名不存在,此时抛出 `UnknownAccountException` 异常,Shiro会捕获该异常并根据配置进行相应的处理(比如提示用户账号不存在等)。 + if (user == null) { throw new UnknownAccountException("账号或密码不正确"); } - - //密码错误 - if(!password.equals(user.getPassword())) { + + // 将用户输入的密码与从数据库中查询到的用户实体对象中存储的密码进行比对,如果不一致,说明密码错误,抛出 `IncorrectCredentialsException` 异常,Shiro同样会根据配置进行处理(例如提示密码错误等)。 + if (!password.equals(user.getPassword())) { throw new IncorrectCredentialsException("账号或密码不正确"); } - - //账号锁定 - if(user.getStatus() == SysUserStatusEnum.LOCKED){ - throw new LockedAccountException("账号已被锁定,请联系管理员"); + + // 判断用户账号的状态,如果状态为 `SysUserStatusEnum.LOCKED`(表示账号已被锁定,这里 `SysUserStatusEnum` 应该是一个自定义的枚举类型,用于表示用户账号的不同状态), + // 则抛出 `LockedAccountException` 异常,告知用户账号已被锁定,需联系管理员处理,Shiro会相应地进行处理,比如禁止登录等操作。 + if (user.getStatus() == SysUserStatusEnum.LOCKED) { + throw new LockedAccountException("账号已被锁定,请联系管理员"); } - + + // 如果上述验证都通过,创建一个 `SimpleAuthenticationInfo` 对象,将查询到的用户对象、密码以及当前 `Realm` 的名称(通过 `getName()` 方法获取)传入构造函数。 + // 这个对象会被Shiro用于后续的认证相关处理,表示当前用户的认证信息已通过验证,后续在会话等相关处理中会用到这些信息。 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user, password, getName()); - + return info; - } + } -} +} \ No newline at end of file diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/interceptor/SettingsInterceptor.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/interceptor/SettingsInterceptor.java index d0c947a..6a13f6b 100644 --- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/interceptor/SettingsInterceptor.java +++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/interceptor/SettingsInterceptor.java @@ -10,12 +10,28 @@ import org.springframework.web.servlet.ModelAndView; import com.tamguo.modules.sys.utils.Setting; +// 使用@Component注解将这个类标记为Spring组件,使得Spring能够扫描并管理这个类,在需要的时候可以自动将其实例注入到其他依赖它的类中。 +// 这个类实现了HandlerInterceptor接口,用于拦截Spring Web应用中的请求,在请求处理的不同阶段执行自定义的逻辑,比如在请求前做一些准备工作、在请求处理后设置一些属性或者在整个请求结束后进行资源清理等。 @Component public class SettingsInterceptor implements HandlerInterceptor { - @Resource - private Setting setting; + // 使用@Resource注解进行依赖注入,将名为"setting"的Bean(从Spring容器中查找,这里应该是一个实现了相关业务逻辑的Setting类的实例,可能用于获取系统相关的设置信息等)注入到当前类的setting属性中, + // 以便后续在拦截器的各个方法中使用这些设置信息来完成相应的功能,比如传递给视图层等操作。 + @Resource + private Setting setting; + /** + * 这个方法在请求处理之前被调用,也就是在请求到达具体的Controller方法之前执行。 + * 它可以用于进行一些前置的验证、权限检查或者准备工作等操作。 + * 返回值为布尔类型,如果返回true,则表示允许请求继续向后传递,进入到Controller方法进行处理;如果返回false,则会中断请求,后续的Controller方法以及其他拦截器的后续方法都不会被执行。 + * 在当前实现中,直接返回了true,表示允许所有请求继续往后处理,不做额外的前置拦截操作(可根据实际业务需求添加具体逻辑)。 + * + * @param request 当前的HttpServletRequest对象,包含了请求的相关信息,如请求头、请求参数等,可以通过它获取请求相关的数据进行前置判断等操作。 + * @param response 当前的HttpServletResponse对象,用于设置响应相关的信息,比如响应头、状态码等,如果在前置处理中发现问题需要返回特定的响应给客户端,可以通过它来进行设置。 + * @param handler 表示被拦截的请求对应的处理器对象,通常是Controller中的方法对应的处理器,可以通过它获取一些关于处理方法的信息(在某些复杂的场景下可能会用到)。 + * @return boolean 返回true表示允许请求继续处理,返回false表示拦截请求,中断后续处理流程。 + * @throws Exception 如果在前置处理过程中出现异常,可以抛出异常,Spring会根据配置进行相应的异常处理,比如返回错误页面等操作。 + */ @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { @@ -23,17 +39,39 @@ public class SettingsInterceptor implements HandlerInterceptor { return true; } + /** + * 这个方法在请求被Controller方法处理之后,但在视图渲染之前被调用。 + * 可以用于对请求处理后的结果进行一些修改、添加额外的模型数据或者进行一些通用的设置等操作,使得这些信息能够传递到视图层进行展示等。 + * 在当前实现中,将之前注入的Setting实例通过request.setAttribute方法设置到请求的属性中,键为"setting",这样在视图层(如JSP、Thymeleaf等模板文件中)就可以获取到这个系统设置相关的对象,用于展示系统设置信息或者基于设置信息进行页面逻辑的处理等。 + * + * @param request 当前的HttpServletRequest对象,包含了请求相关的信息,在这里可以通过它来设置一些属性,传递给后续的视图渲染阶段使用。 + * @param response 当前的HttpServletResponse对象,同样可用于设置响应相关的信息,如果在这个阶段需要调整响应的一些内容,可以通过它进行操作。 + * @param handler 表示被拦截的请求对应的处理器对象,即Controller中的方法对应的处理器,可用于获取处理方法相关的一些信息(视具体业务场景决定是否使用)。 + * @param modelAndView 如果Controller方法返回了ModelAndView对象(用于指定视图和传递模型数据),则在这里可以获取并对其进行修改、添加数据等操作;如果Controller方法没有返回ModelAndView(比如直接返回数据等情况),则这个参数可能为null。 + * @throws Exception 如果在这个阶段出现异常,同样可以抛出异常,Spring会根据配置进行相应的异常处理,比如返回错误页面等操作。 + */ @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, - ModelAndView modelAndView) throws Exception { - // 设置系统变量 - request.setAttribute("setting", setting); + ModelAndView modelAndView) throws Exception { + // 设置系统变量 + request.setAttribute("setting", setting); } + /** + * 这个方法在整个请求结束之后被调用,也就是在DispatcherServlet渲染了对应的视图之后执行。 + * 它主要用于进行资源清理工作,比如关闭一些在请求处理过程中打开的资源(如数据库连接、文件流等),释放占用的内存等操作,确保资源的合理使用,避免资源泄漏等问题。 + * 在当前实现中,没有具体的资源清理逻辑(可根据实际业务需求添加,例如关闭自定义的缓存连接、释放一些自定义的线程资源等),只是保留了方法的结构,满足HandlerInterceptor接口的要求。 + * + * @param request 当前的HttpServletRequest对象,包含了请求相关的所有信息,虽然在这个阶段请求已经处理完毕,但可以通过它获取一些请求相关的上下文信息,以便进行针对性的资源清理等操作。 + * @param response 当前的HttpServletResponse对象,用于设置响应相关的信息,同样在这个阶段可以根据响应情况进行一些后续的资源清理等操作(比如清理响应缓存等,不过通常情况较少涉及)。 + * @param handler 表示被拦截的请求对应的处理器对象,即Controller中的方法对应的处理器,通过它可以获取处理方法相关的一些信息,用于判断是否需要进行特定的资源清理操作(视具体业务场景而定)。 + * @param ex 如果在请求处理过程中出现了异常,会将异常对象传递到这里,可以根据异常情况进行一些额外的资源清理或者记录异常相关的日志等操作;如果没有异常发生,则这个参数为null。 + * @throws Exception 如果在进行资源清理等操作过程中又出现了异常,可以再次抛出异常,Spring会根据配置进行相应的异常处理,比如记录错误日志、返回错误页面等操作。 + */ @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { - //在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作) + //在整个请求结束之后被调用,也就是在DispatcherServlet 渲染了对应的视图之后执行(主要是用于进行资源清理工作) } - -} + +} \ No newline at end of file diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/Setting.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/Setting.java index e1eb604..a8fa4de 100644 --- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/Setting.java +++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/Setting.java @@ -4,29 +4,62 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; /** - * Setting - 系统 - * + * Setting类用于存放系统相关的配置信息和一些常量定义,它在整个项目中可以作为一个统一获取系统设置的地方,方便不同模块使用这些配置和常量。 + * 这个类被标记为@Component,意味着它会被Spring容器管理,成为一个Spring Bean,可以通过依赖注入的方式在其他需要的地方使用。 + * 同时,这个类被定义为final,表示它不能被继承,保证了其配置信息和常量的唯一性与稳定性(避免子类对其进行修改导致不符合预期的情况)。 + * * @author candy.tam * */ @Component public final class Setting { - /** 域名 */ - @Value(value="${domain.name}") + /** + * 域名属性,用于存储系统所使用的域名信息。 + * 通过@Value注解,从配置文件(通常是application.properties或application.yml等)中读取名为"domain.name"的配置项的值,并注入到这个domain属性中。 + * 在项目中,例如生成完整的URL地址、进行域名相关的验证或者配置跨域等场景时可能会用到该域名信息。 + */ + @Value(value = "${domain.name}") public String domain; - /** 静态资源地址*/ - @Value(value="${static.domain}") + + /** + * 静态资源地址属性,用于存储系统中静态资源(如图片、样式文件、脚本文件等)所在的域名或者路径相关信息。 + * 同样使用@Value注解从配置文件中获取名为"static.domain"的配置项的值,注入到这个staticDomain属性中。 + * 当项目需要引用静态资源时,就可以通过这个属性来构建正确的资源访问路径,确保静态资源能够被正确加载和显示。 + */ + @Value(value = "${static.domain}") public String staticDomain; - @Value(value="${version}") + + /** + * 版本属性,用于存储系统的版本信息。 + * 借助@Value注解从配置文件里读取名为"version"的配置项的值,并赋给这个version属性。 + * 在项目的版本管理、接口版本控制或者前端展示当前系统版本等场景中,该版本信息会发挥相应的作用。 + */ + @Value(value = "${version}") public String version; - /** 真题 */ + + /** + * 真题类型的常量定义,值为"1",用于在项目中标识试卷类型为真题的情况。 + * 例如在处理试卷相关业务逻辑时,通过判断试卷的类型是否等于这个常量来确定它是否是真题,方便进行不同类型试卷的分类处理、查询或者展示等操作。 + */ public final String PAPER_TYPE_ZHENTI = "1"; - /** 模拟*/ + + /** + * 模拟类型的常量定义,值为"2",用于表示试卷类型是模拟题的情况。 + * 和真题类型常量类似,在试卷业务逻辑中可用于区分模拟题试卷,按照模拟题的特定规则进行相关处理,比如生成模拟题试卷、统计模拟题答题情况等。 + */ public final String PAPER_TYPE_MONI = "2"; - /** 押题*/ + + /** + * 押题类型的常量定义,值为"3",用于标记试卷类型为押题的情况。 + * 在涉及押题试卷相关的业务流程中,依靠这个常量来识别押题试卷,进而执行诸如押题试卷的推荐、分析押题命中率等相关操作。 + */ public final String PAPER_TYPE_YATI = "3"; - /** 名校 */ + + /** + * 名校类型的常量定义,值为"4",用于界定试卷类型是与名校相关的情况(具体含义可能根据业务场景而定,比如名校的真题、名校的模拟题等)。 + * 在处理与名校试卷有关的业务逻辑时,利用这个常量来区分名校试卷,进行相应的展示、筛选或者分析等操作。 + */ public final String PAPER_TYPE_MINGXIAO = "4"; - -} + +} \ No newline at end of file diff --git a/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/ShiroUtils.java b/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/ShiroUtils.java index d2604ef..5628572 100644 --- a/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/ShiroUtils.java +++ b/tamguo-oms/src/main/java/com/tamguo/modules/sys/utils/ShiroUtils.java @@ -6,44 +6,100 @@ import org.apache.shiro.subject.Subject; import com.tamguo.modules.sys.model.SysUserEntity; +// 这个类是一个工具类,提供了一系列与Shiro框架交互的便捷方法,用于获取Shiro相关的对象(如会话、当前用户等)以及执行一些常见的操作(如设置会话属性、判断登录状态、注销等),方便在项目的不同地方复用这些操作逻辑,避免重复编写获取Shiro相关信息的代码。 public class ShiroUtils { + /** + * 获取当前用户的Shiro会话对象。 + * 通过调用Shiro的SecurityUtils工具类的getSubject()方法获取当前的Subject(代表当前执行的用户主体),然后再调用其getSession()方法获取对应的会话对象。 + * 会话对象可以用于存储用户在一次会话期间的相关数据,例如临时的用户状态、权限缓存等信息,在整个应用中不同模块间共享这些会话数据来实现一些功能。 + * @return 返回当前用户的Shiro会话对象。 + */ public static Session getSession() { return SecurityUtils.getSubject().getSession(); } + /** + * 获取当前的Subject对象。 + * Subject对象代表了当前执行操作的用户主体,通过它可以进行很多与认证、授权以及会话管理等相关的操作,比如获取用户信息、判断用户是否具有某个权限等。 + * 在Shiro框架中,它是与当前用户交互的核心入口点,很多Shiro相关的功能调用都依赖于获取到的这个Subject对象。 + * @return 返回当前的Subject对象。 + */ public static Subject getSubject() { return SecurityUtils.getSubject(); } + /** + * 获取当前登录用户对应的SysUserEntity对象。 + * 通过调用SecurityUtils.getSubject().getPrincipal()方法获取当前用户主体的认证信息(在通常情况下,登录成功后会将用户相关的实体对象或者关键信息存储在这里作为认证信息), + * 然后将其强制转换为SysUserEntity类型,该类型应该是项目中自定义的表示系统用户的实体类,包含了如用户名、密码、用户权限等用户相关的详细信息,方便在业务逻辑中使用具体的用户信息进行后续操作。 + * @return 返回当前登录用户对应的SysUserEntity对象,如果当前用户未登录,则可能会抛出类型转换异常(实际使用中可根据业务场景进行更合理的异常处理)。 + */ public static SysUserEntity getUser() { - return (SysUserEntity)SecurityUtils.getSubject().getPrincipal(); + return (SysUserEntity) SecurityUtils.getSubject().getPrincipal(); } + /** + * 获取当前登录用户的用户代码(具体含义根据项目中SysUserEntity类里userCode属性的定义而定,可能是用户名、用户编号等唯一标识用户的代码)。 + * 先调用getUser()方法获取当前登录用户对应的SysUserEntity对象,然后再调用其getUserCode()方法获取用户代码属性的值,方便在业务逻辑中使用用户代码进行一些操作,比如记录操作日志时关联用户、进行权限判断等基于用户代码的业务场景。 + * @return 返回当前登录用户的用户代码。 + */ public static String getUserCode() { return getUser().getUserCode(); } - + + /** + * 设置当前用户会话中的属性值。 + * 通过先调用getSession()方法获取当前用户的会话对象,然后使用其setAttribute()方法将要存储的键值对(key-value)形式的数据存入会话中, + * 这样在同一会话的其他地方(比如后续的请求处理中)就可以通过相同的键来获取对应的值,实现会话级别的数据共享和传递。 + * @param key 要设置的属性的键,用于后续获取属性值时作为标识。 + * @param value 要设置的属性的值,即要存入会话中的具体数据内容。 + */ public static void setSessionAttribute(Object key, Object value) { getSession().setAttribute(key, value); } + /** + * 获取当前用户会话中指定键对应的属性值。 + * 首先获取当前用户的会话对象(通过调用getSession()方法),然后使用其getAttribute()方法根据传入的键(key)来获取对应的属性值, + * 如果键不存在,则返回null,可用于在会话中获取之前存储的临时数据,比如从一个请求中存入会话的中间计算结果,在后续请求中通过这个方法获取并继续使用。 + * @param key 要获取的属性对应的键,用于在会话中查找相应的值。 + * @return 返回当前用户会话中指定键对应的属性值,如果键不存在则返回null。 + */ public static Object getSessionAttribute(Object key) { return getSession().getAttribute(key); } + /** + * 判断当前用户是否已经登录。 + * 通过检查SecurityUtils.getSubject().getPrincipal()返回的用户主体认证信息是否为null来判断当前用户是否登录, + * 如果不为null,表示当前有用户已经通过认证登录系统了,返回true;如果为null,则表示当前没有用户登录,返回false,方便在业务逻辑中根据登录状态来决定是否允许执行某些操作,比如只有登录用户才能访问的页面或接口等情况。 + * @return 返回布尔值,true表示当前用户已登录,false表示当前用户未登录。 + */ public static boolean isLogin() { - return SecurityUtils.getSubject().getPrincipal() != null; + return SecurityUtils.getSubject().getPrincipal()!= null; } + /** + * 执行用户注销操作。 + * 调用SecurityUtils.getSubject().logout()方法,该方法会清除当前用户的认证信息、会话数据等相关内容,使当前用户退出登录状态, + * 常用于用户主动点击注销按钮或者系统根据某些条件(如长时间未操作等)自动执行注销的场景,确保用户退出系统后相关数据的安全性以及资源的合理释放。 + */ public static void logout() { SecurityUtils.getSubject().logout(); } - + + /** + * 获取保存在会话中的验证码信息(根据传入的键来查找对应的验证码值)。 + * 先通过调用getSessionAttribute(key)方法从会话中获取指定键对应的对象,然后将其转换为字符串类型(假设验证码在会话中是以字符串形式存储的), + * 这里有一行被注释掉的代码getSession().removeAttribute(key),可能原本的意图是在获取验证码后从会话中移除该验证码,以避免重复使用等情况(可根据实际业务需求决定是否启用该逻辑)。 + * @param key 用于在会话中查找验证码的键,在生成验证码并存储到会话时使用的相同键来获取对应的验证码信息。 + * @return 返回从会话中获取到的验证码字符串,如果键不存在或者获取到的对象转换字符串失败等情况,可能会抛出异常(实际使用中可根据业务场景进行合理的异常处理)。 + */ public static String getKaptcha(String key) { String kaptcha = getSessionAttribute(key).toString(); -// getSession().removeAttribute(key); +// getSession().removeAttribute(key); return kaptcha; } -} +} \ No newline at end of file