pache shiro是一个安全认证框架,和spring security相比,在于他使用了比较简洁易懂的认证和授权方式。其提供的native-session(即把用户认证后的授权信息保存在其自身提供Session中)机制,这样就可以和HttpSession、EJB Session Bean的基于容器的Session脱耦,到和客户端应用、Flex应用、远程方法调用等都可以使用它来配置权限认证。 在exit-web-framework里的vcs-admin例子用到该框架,具体使用说明可以参考官方帮助文档。在这里主要讲解如何与spring结合、动态创建filterchaindefinitions、以及认证、授权、和缓存处理。
apache shiro 结合spring
Shiro 拥有对Spring Web 应用程序的一流支持。在Web 应用程序中,所有Shiro 可访问的万恶不请求必须通过一个主要的Shiro 过滤器。该过滤器本身是极为强大的,允许临时的自定义过滤器链基于任何URL 路径表达式执行。 在Shiro 1.0 之前,你不得不在Spring web 应用程序中使用一个混合的方式,来定义Shiro 过滤器及所有它在web.xml中的配置属性,但在Spring XML 中定义SecurityManager。这有些令人沮丧,由于你不能把你的配置固定在一个地方,以及利用更为先进的Spring 功能的配置能力,如PropertyPlaceholderConfigurer 或抽象bean 来固定通用配置。现在在Shiro 1.0 及以后版本中,所有Shiro 配置都是在Spring XML 中完成的,用来提供更为强健的Spring 配置机制。以下是如何在基于Spring web 应用程序中配置Shiro: web.xml:
- <!-- Spring ApplicationContext配置文件的路径,可使用通配符,多个路径用,号分隔 此参数用于后面的Spring Context Loader -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>
- classpath*:/applicationContext-shiro.xml
- </param-value>
- </context-param>
- <!-- shiro security filter -->
- <filter>
- <!-- 这里的filter-name要和spring的applicationContext-shiro.xml里的
- org.apache.shiro.spring.web.ShiroFilterFactoryBean的bean name相同 -->
- <filter-name>shiroSecurityFilter</filter-name>
- <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
- <init-param>
- <param-name>targetFilterLifecycle</param-name>
- <param-value>true</param-value>
- </init-param>
- </filter>
- <filter-mapping>
- <filter-name>shiroSecurityFilter</filter-name>
- <url-pattern>/*</url-pattern>
- </filter-mapping>
applicationContext-shiro.xml文件中,定义web支持的SecurityManager和"shiroSecurityFilter"bean将会被web.xml 引用。
- <bean id="shiroSecurityFilter">
- <!-- shiro的核心安全接口 -->
- <property name="securityManager" ref="securityManager" />
- <!-- 要求登录时的链接 -->
- <property name="loginUrl" value="/login.jsp" />
- <!-- 登陆成功后要跳转的连接 -->
- <property name="successUrl" value="/index.jsp" />
- <!-- 未授权时要跳转的连接 -->
- <property name="unauthorizedUrl" value="/unauthorized.jsp" />
- <!-- shiro连接约束配置 -->
- <property name="filterChainDefinitions">
- <value>
- /login = authc
- /logout = logout
- /resource/** = anon
- </value>
- </property>
- </bean>
- <bean id="securityManager">
- </bean>
- <bean id="lifecycleBeanPostProcessor"/>
启用Shiro注解
在独立应用程序和Web应用程序中,你可能想为安全检查使用Shiro 的注释(例如,@RequiresRoles,@RequiresPermissions 等等)。这需要Shiro 的Spring AOP 集成来扫描合适的注解类以及执行必要的安全逻辑。以下是如何使用这些注解的。只需添加这两个bean 定义到applicationContext-shiro.xml 中:
- <bean depends-on="lifecycleBeanPostProcessor"/>
- <bean>
- <property name="securityManager" ref="securityManager"/>
- </bean>
动态创建filterchaindefinitions
有时,在某些系统想通过读取数据库来定义org.apache.shiro.spring.web.ShiroFilterFactoryBean的filterChainDefinitions。这样能够通过操作界面或者维护后台来管理系统的链接。
在shrio与spring集成好了以后,调试源码的高人可能已经注意到。项目启动时,shrio通过自己的org.apache.shiro.spring.web.ShiroFilterFactoryBean类的filterChainDefinitions(授权规则定义)属性转换为一个filterChainDefinitionMap,转换完成后交给ShiroFilterFactoryBean保管。ShiroFilterFactoryBean根据授权(AuthorizationInfo类)后的信息去判断哪些链接能访问哪些链接不能访问。filterChainDefinitionMap里面的键就是链接URL,值就是存在什么条件才能访问该链接,如perms、roles。filterChainDefinitionMap是一个Map,shiro扩展出一个Map的子类Ini.Section
现在有一张表的描述实体类,以及数据访问:
- @Entity
- @Table(name="TB_RESOURCE")
- public class Resource implements Serializable {
- //主键id
- @Id
- private String id;
- //action url
- private String value;
- //shiro permission;
- private String permission;
- //------------------Getter/Setter---------------------//
- }
- @Repository
- public class ResourceDao extends BasicHibernateDao<Resource, String> {
- }
通过该类可以知道permission字段和value就是filterChainDefinitionMap的键/值,用spring FactoryBean接口的实现getObject()返回Section给filterChainDefinitionMap即可
- public class ChainDefinitionSectionMetaSource implements FactoryBean<Ini.Section>{
- @Autowired
- private ResourceDao resourceDao;
- private String filterChainDefinitions;
- /**
- * 默认premission字符串
- */
- public static final String PREMISSION_STRING="perms[\"{0}\"]";
- public Section getObject() throws BeansException {
- //获取所有Resource
- List<Resource> list = resourceDao.getAll();
- Ini ini = new Ini();
- //加载默认的url
- ini.load(filterChainDefinitions);
- Ini.Section section = ini.getSection(Ini.DEFAULT_SECTION_NAME);
- //循环Resource的url,逐个添加到section中。section就是filterChainDefinitionMap,
- //里面的键就是链接URL,值就是存在什么条件才能访问该链接
- for (Iterator<Resource> it = list.iterator(); it.hasNext();) {
- Resource resource = it.next();
- //如果不为空值添加到section中
- if(StringUtils.isNotEmpty(resource.getValue()) && StringUtils.isNotEmpty(resource.getPermission())) {
- section.put(resource.getValue(), MessageFormat.format(PREMISSION_STRING,resource.getPermission()));
- }
- }
- return section;
- }
- /**
- * 通过filterChainDefinitions对默认的url过滤定义
- *
- * @param filterChainDefinitions 默认的url过滤定义
- */
- public void setFilterChainDefinitions(String filterChainDefinitions) {
- this.filterChainDefinitions = filterChainDefinitions;
- }
- public Class<?> getObjectType() {
- return this.getClass();
- }
- public boolean isSingleton() {
- return false;
- }
- }
定义好了chainDefinitionSectionMetaSource后修改applicationContext-shiro.xml文件
- <bean id="chainDefinitionSectionMetaSource">
- <property name="filterChainDefinitions">
- <value>
- /login = authc
- /logout = logout
- /resource/** = anon
- </value>
- </property>
- </bean>
- <bean id="shiroSecurityFilter">
- <property name="securityManager" ref="securityManager" />
- <property name="loginUrl" value="/login.jsp" />
- <property name="successUrl" value="/index.jsp" />
- <property name="unauthorizedUrl" value="/unauthorized.jsp" />
- <!-- shiro连接约束配置,在这里使用自定义的动态获取资源类 -->
- <property name="filterChainDefinitionMap" ref="chainDefinitionSectionMetaSource" />
- </bean>
- <bean id="securityManager">
- </bean>
- <bean id="lifecycleBeanPostProcessor"/>
shiro数据库认证、授权
在shiro认证和授权主要是两个类,就是org.apache.shiro.authc.AuthenticationInfo和org.apache.shiro.authz.AuthorizationInfo。该两个类的处理在org.apache.shiro.realm.AuthorizingRealm中已经给出了两个抽象方法。就是:
- /**
- * Retrieves the AuthorizationInfo for the given principals from the underlying data store. When returning
- * an instance from this method, you might want to consider using an instance of
- * {@link org.apache.shiro.authz.SimpleAuthorizationInfo SimpleAuthorizationInfo}, as it is suitable in most cases.
- *
- * @param principals the primary identifying principals of the AuthorizationInfo that should be retrieved.
- * @return the AuthorizationInfo associated with this principals.
- * @see org.apache.shiro.authz.SimpleAuthorizationInfo
- */
- protected abstract AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals);
- /**
- * Retrieves authentication data from an implementation-specific datasource (RDBMS, LDAP, etc) for the given
- * authentication token.
- * <p/>
- * For most datasources, this means just 'pulling' authentication data for an associated subject/user and nothing
- * more and letting Shiro do the rest. But in some systems, this method could actually perform EIS specific
- * log-in logic in addition to just retrieving data - it is up to the Realm implementation.
- * <p/>
- * A {@code null} return value means that no account could be associated with the specified token.
- *
- * @param token the authentication token containing the user's principal and credentials.
- * @return an {@link AuthenticationInfo} object containing account data resulting from the
- * authentication ONLY if the lookup is successful (i.e. account exists and is valid, etc.)
- * @throws AuthenticationException if there is an error acquiring data or performing
- * realm-specific authentication logic for the specified <tt>token</tt>
- */
- protected abstract AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException;
doGetAuthenticationInfo(AuthenticationToken token)(认证/登录方法)会返回一个AuthenticationInfo,就是认证信息。是一个对执行及对用户的身份验证(登录)尝试负责的方法。当一个用户尝试登录时,该逻辑被认证器执行。认证器知道如何与一个或多个Realm协调来存储相关的用户/帐户信息。从这些Realm中获得的数据被用来验证用户的身份来保证用户确实是他们所说的他们是谁。
doGetAuthorizationInfo(PrincipalCollection principals)是负责在应用程序中决定用户的访问控制的方法。它是一种最终判定用户是否被允许做某件事的机制。与doGetAuthenticationInfo(AuthenticationToken token)相似,doGetAuthorizationInfo(PrincipalCollection principals) 也知道如何协调多个后台数据源来访问角色恶化权限信息和准确地决定用户是否被允许执行给定的动作。
简单的一个用户和一个资源实体:
- @Entity
- @Table(name="TB_RESOURCE")
- public class Resource implements Serializable {
- //主键id
- @Id
- private String id;
- //action url
- private String value;
- //shiro permission;
- private String permission;
- //------------------Getter/Setter---------------------//
- }
- @Entity
- @Table(name="TB_USER")
- @SuppressWarnings("serial")
- public class User implements Serializable {
- //主键id
- @Id
- private String id;
- //登录名称
- private String username;
- //登录密码
- private String password;
- //拥有能访问的资源/链接()
- private List<Resource> resourcesList = new ArrayList<Resource>();
- //-------------Getter/Setter-------------//
- }
- @Repository
- public class UserDao extends BasicHibernateDao<User, String> {
- public User getUserByUsername(String username) {
- return findUniqueByProperty("username", username);
- }
- }
实现org.apache.shiro.realm.AuthorizingRealm中已经给出了两个抽象方法:
- public class ShiroDataBaseRealm extends AuthorizingRealm{
- @Autowired
- private UserDao userDao;
- /**
- *
- * 当用户进行访问链接时的授权方法
- *
- */
- protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
- if (principals == null) {
- throw new AuthorizationException("Principal对象不能为空");
- }
- User user = (User) principals.fromRealm(getName()).iterator().next();
- //获取用户响应的permission
- List<String> permissions = CollectionUtils.extractToList(user.getResourcesList(), "permission",true);
- SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
- info.addStringPermissions(permissions);
- return info;
- }
- /**
- * 用户登录的认证方法
- *
- */
- protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
- UsernamePasswordToken usernamePasswordToken = (UsernamePasswordToken) token;
- String username = usernamePasswordToken.getUsername();
- if (username == null) {
- throw new AccountException("用户名不能为空");
- }
- User user = userDao.getUserByUsername(username);
- if (user == null) {
- throw new UnknownAccountException("用户不存在");
- }
- return new SimpleAuthenticationInfo(user,user.getPassword(),getName());
- }
- }
定义好了ShiroDataBaseRealm后修改applicationContext-shiro.xml文件
- <bean id="chainDefinitionSectionMetaSource">
- <property name="filterChainDefinitions">
- <value>
- /login = authc
- /logout = logout
- /resource/** = anon
- </value>
- </property>
- </bean>
- <bean id="shiroSecurityFilter">
- <property name="securityManager" ref="securityManager" />
- <property name="loginUrl" value="/login.jsp" />
- <property name="successUrl" value="/index.jsp" />
- <property name="unauthorizedUrl" value="/unauthorized.jsp" />
- <!-- shiro连接约束配置,在这里使用自定义的动态获取资源类 -->
- <property name="filterChainDefinitionMap" ref="chainDefinitionSectionMetaSource" />
- </bean>
- <bean id="shiroDataBaseRealm">
- <!-- MD5加密 -->
- <property name="credentialsMatcher">
- <bean>
- <property name="hashAlgorithmName" value="MD5" />
- </bean>
- </property>
- </bean>
- <bean id="securityManager">
- <property name="realm" ref="shiroDataBaseRealm" />
- </bean>
- <bean id="lifecycleBeanPostProcessor"/>
shiro EHcache 与 Spring EHcache集成
shiro CacheManager创建并管理其他Shiro组件使用的Cache实例生命周期。因为Shiro能够访问许多后台数据源,如:身份验证,授权和会话管理,缓存在框架中一直是一流的架构功能,用来在同时使用这些数据源时提高性能。任何现代开源和/或企业的缓存产品能够被插入到Shiro 来提供一个快速及高效的用户体验。
自从spring 3.1问世后推出了缓存功能后,提供了对已有的 Spring 应用增加缓存的支持,这个特性对应用本身来说是透明的,通过缓存抽象层,使得对已有代码的影响降低到最小。
该缓存机制针对于 Java 的方法,通过给定的一些参数来检查方法是否已经执行,Spring 将对执行结果进行缓存,而无需再次执行方法。
可通过下列配置来启用缓存的支持:
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:cache="http://www.springframework.org/schema/cache"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/cache http://www.springframework.org/schema/cache/spring-cache.xsd">
<!-- 使用缓存annotation 配置 -->
<cache:annotation-driven cache-manager="ehCacheManager" />
</beans>
@Cacheable和**@CacheEvict**来对缓存进行操作
@Cacheable:负责将方法的返回值加入到缓存中
@CacheEvict:负责清除缓存
/**声明了一个名为 persons 的缓存区域,当调用该方法时,Spring 会检查缓存中是否存在 personId 对应的值。*/
@Cacheable("persons")
public Person profile(Long personId) { ... }
/**指定多个缓存区域。Spring 会一个个的检查,一旦某个区域存在指定值时则返回*/
@Cacheable({"persons", "profiles"})
public Person profile(Long personId) { ... }
</code>
</pre>
<pre>
<code>
/**清空所有缓存*/
@CacheEvict(value="persons",allEntries=true)
public Person profile(Long personId, Long groundId) { ... }
/**或者根据条件决定是否缓存*/
@CacheEvict(value="persons", condition="personId > 50")
public Person profile(Long personId) { ... }
在shiro里面会有授权缓存。可以通过AuthorizingRealm类中指定缓存名称。就是authorizationCacheName属性。当shiro为用户授权一次之后将会把所有授权信息都放进缓存中。现在有个需求。当在更新用户或者删除资源和更新资源的时候,要刷新一下shiro的授权缓存,给shiro重新授权一次。因为当更新用户或者资源时,很有可能已经把用户本身已有的资源去掉。不给用户访问。所以。借助spring的缓存工厂和shiro的缓存能够很好的实现这个需求。
将applicationContext-shiro.xml文件添加缓存
<bean id="chainDefinitionSectionMetaSource">
<property name="filterChainDefinitions" >
<value>
/login = authc
/logout = logout
/resource/** = anon
</value>
</property>
</bean>
<bean id="shiroSecurityFilter">
<property name="securityManager" ref="securityManager" />
<property name="loginUrl" value="/login.jsp" />
<property name="successUrl" value="/index.jsp" />
<property name="unauthorizedUrl" value="/unauthorized.jsp" />
<!-- shiro连接约束配置,在这里使用自定义的动态获取资源类 -->
<property name="filterChainDefinitionMap" ref="chainDefinitionSectionMetaSource" />
</bean>
<bean id="shiroDataBaseRealm">
<!-- MD5加密 -->
<property name="credentialsMatcher">
<bean>
<property name="hashAlgorithmName" value="MD5" />
</bean>
</property>
<property name="authorizationCacheName" value="shiroAuthorizationCache" />
</bean>
<bean id="securityManager">
<property name="realm" ref="shiroDataBaseRealm" />
<property name="cacheManager" ref="cacheManager" />
</bean>
<bean id="lifecycleBeanPostProcessor"/>
<!-- 使用缓存annotation 配置 --/>
<cache:annotation-driven cache-manager="ehCacheManager" />
<!-- spring对ehcache的缓存工厂支持 -->
<bean id="ehCacheManagerFactory">
<property name="configLocation" value="classpath:ehcache.xml" />
<property name="shared" value="false" />
</bean>
<!-- spring对ehcache的缓存管理 -->
<bean id="ehCacheManager">
<property name="cacheManager" ref="ehCacheManagerFactory"></property>
</bean>
<!-- shiro对ehcache的缓存管理直接使用spring的缓存工厂 -->
<bean id="cacheManager">
<property name="cacheManager" ref="ehCacheManagerFactory" />
</bean>
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<!--
maxElementsInMemory为缓存对象的最大数目,
eternal设置是否永远不过期,
timeToIdleSeconds对象处于空闲状态的最多秒数,
timeToLiveSeconds对象处于缓存状态的最多秒数
-->
<diskStore path="java.io.tmpdir"/>
<cache name="shiroAuthorizationCache" maxElementsInMemory="300" eternal="false" timeToLiveSeconds="600" overflowToDisk="false"/>
</ehcache>
public class UserDao extends BasicHibernateDao<User, String> {
public User getUserByUsername(String username) {
return findUniqueByProperty("username", username);
}
@CacheEvict(value="shiroAuthorizationCache",allEntries=true)
public void saveUser(User entity) {
save(entity);
}
}
@Repository
public class ResourceDao extends BasicHibernateDao<Resource, String> {
@CacheEvict(value="shiroAuthorizationCache",allEntries=true)
public void saveResource(Resource entity) {
save(entity);
}
@CacheEvict(value="shiroAuthorizationCache",allEntries=true)
public void deleteResource(Resource entity) {
delete(entity);
}
}
当userDao或者reaourceDao调用了相应带有缓存注解的方法,都会将AuthorizingRealm类中的缓存去掉。那么就意味着 shiro在用户访问链接时要重新授权一次。
整个apache shiro的使用,vcs admin项目和vcs admin jpa中都会有例子。可以参考showcase/vcs_admin或者showcase/vcs_admin_jpa项目中的例子去理解。。
相关推荐
Apache Shiro 是一个轻量级的安全管理框架,与 Spring Security 相比,它的认证和授权流程更为简单易懂。Shiro 提供了原生会话(native-session)机制,允许在不依赖容器的 Session 实现情况下,存储和管理用户的...
Apache Shiro是一个功能强大且易于使用的Java安全框架,它提供了认证、授权、加密、会话...整合时需要注意Shiro与Spring的依赖关系、配置的正确性以及安全策略的制定。掌握这些知识点对于开发安全的Web应用至关重要。
总之,Apache Shiro与Spring MVC的整合为开发者提供了一种简单有效的方式来实现Web应用的安全管理。通过灵活的配置和扩展,开发者可以快速构建出具备用户认证、授权功能的系统,提升应用的安全性。
总之,Spring框架结合Apache Shiro,可以轻松实现身份验证和授权管理。Shiro的易用性和灵活性使得它成为Java Web应用安全控制的理想选择。通过合理的配置和业务代码的集成,我们可以构建起一套完整且强大的权限管理...
在本文中,我们将深入探讨如何将Spring框架与Apache Shiro安全框架整合,以实现一个强大的权限控制模块。Spring是企业级应用开发的事实标准,而Shiro则是一个轻量级的安全框架,提供了身份验证、授权、会话管理和...
Apache Shiro 是一个强大且易用的 Java 安全框架,提供了身份认证、授权、会话管理和加密等全面的安全服务。Spring 框架则是一个全面的企业级应用开发框架,包括依赖注入、AOP(面向切面编程)、MVC、事务管理等功能...
SSM框架是由Spring、Spring MVC和MyBatis三个组件组成的,而Apache Shiro则是一个强大且易用的Java安全框架,提供了认证、授权、加密和会话管理功能。接下来,我们将深入探讨如何将Shiro与SSM框架整合,以实现细致的...
SpringMVC与Shiro是两个在Java Web开发中常用的框架,SpringMVC主要负责处理控制器层,而Shiro则是一个强大的安全认证与授权框架。它们的结合使用可以帮助开发者构建安全、高效的Web应用。 1. SpringMVC框架 ...
SSM(Spring、Struts2、MyBatis)框架与Apache Shiro的整合是非Maven项目中常见的安全控制实现方式。Shiro是一个强大且易用的Java安全框架,提供了认证、授权、加密和会话管理功能,可以非常方便地与Spring、Struts2...
### Apache Shiro 与 Spring MVC 的集成应用 在软件开发领域,尤其是对于那些涉及用户登录、权限控制的应用来说,安全框架的重要性不言而喻。Apache Shiro 作为一款功能强大的安全框架,在Java应用的安全管理方面...
**Shiro与Spring整合**: 在Shiro 1.0之后,所有的Shiro配置都可以放在Spring XML文件中,使得配置更集中且易于管理。在`web.xml`中,你需要定义一个名为`shiroSecurityFilter`的过滤器,并指定Spring配置文件的位置...
在本文中,我们将深入探讨如何使用Spring Boot与Apache Shiro框架来构建一个权限管理系统。Spring Boot因其简洁的配置和快速的开发效率而受到广大开发者喜爱,而Shiro则是一个轻量级的安全框架,用于实现身份认证、...
Apache Shiro 是一个强大且易用的 Java 安全框架,提供身份认证、授权、会话管理和加密等核心功能。在 Java Web 应用中,Shiro 可以与 Spring 框架集成,实现更灵活的安全控制。下面将详细介绍如何在 Web 应用中配置...
Spring 整合 Shiro 并扩展使用 EL 表达式实例详解 本文将详细介绍 Spring 整合 Shiro 框架,并通过扩展使用 Spring 的 EL 表达式来实现权限控制。Shiro 是一个轻量级的权限控制框架,应用非常广泛。下面是 Spring ...
Apache Shiro 是一个强大且易用的 Java 安全框架,提供身份认证、授权、加密和会话管理功能,简化了开发人员在应用程序中处理安全性的任务。在单机版的 Shiro 整合中,它通常与 SpringMVC、Mybatis 框架以及 Redis ...
Apache Shiro 是一个强大且易用的 Java 安全框架,它提供了认证、授权、加密以及会话管理功能,可以非常方便地与 Spring MVC 框架进行集成,以实现全面的安全控制。以下是对 Shiro 在 Spring MVC 中集成使用的详细...
首先,在Maven项目中,我们需要引入Shiro的相关依赖,包括核心模块(`shiro-core`)、Web支持模块(`shiro-web`)、EhCache缓存模块(`shiro-ehcache`)以及Spring整合模块(`shiro-spring`)。同时,还需要一个日志...
SpringBoot整合Shiro是一个常见的Java Web安全框架集成实践,它使得在SpringBoot应用中实现用户认证和授权变得简单。Shiro框架提供了丰富的功能,包括身份验证、授权、会话管理和安全控制,为开发者构建安全的应用...
当Shiro与Spring框架结合使用时,可以更好地整合到现有的Spring应用中,实现更灵活和模块化的安全控制。以下将详细介绍基于Spring框架的Shiro配置方法。 首先,我们需要在`web.xml`中配置Shiro的过滤器。这一步是...
《SpringBoot整合Shiro实战详解》 在Java开发领域,SpringBoot以其简洁高效的特性深受开发者喜爱,而Shiro作为一款轻量级的安全框架,为应用提供了权限管理、认证和会话管理等功能。当我们需要在SpringBoot项目中...