Shiro认证
Apache Shiro 是一个强大而灵活的 Java 安全框架,主要用于处理身份认证、授权、加密和会话管理等。以下是关于 Apache Shiro 的详细介绍:
一、主要功能
-
身份认证:
- 确定用户的身份。可以验证用户提供的凭证(如用户名和密码)与存储在系统中的信息是否匹配。
- 支持多种认证方式,如用户名 / 密码、数字证书、LDAP 等。
-
授权:
- 控制用户对系统资源的访问权限。可以根据用户的角色、权限等信息来决定用户是否能够访问特定的功能或资源。
- 提供了灵活的授权策略,可以基于角色、权限、资源等进行授权。
-
加密:
- 对敏感数据进行加密,保护数据的安全性。
- 支持多种加密算法,如 AES、DES 等。
-
会话管理:
- 管理用户的会话状态,包括登录状态、超时处理等。
- 提供了会话的创建、销毁、验证等功能。
5.等等。。。。。。
二, 快速上手:
添加依赖
<dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.4.1</version></dependency>
配置shiro.ini文件
#对用户信息进行配置
[users]
#用户账号密码
#配置规则:用户账号=密码,角色1,角色2
admin=123456,管理员
czkt=111111,客户经理
#对权限信息进行配置,基于角色配置
[roles]
#角色和权限
#配置规则:角色名称=权限1,权限2,权限字符串可使用通配符配置
管理员=user:*,role:*
#客户经理只能对用户进行列表和详细的查看操作
客户经理=user:list,user:view
认证测试
package com.bdqn.shiro;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.realm.text.IniRealm;
import org.apache.shiro.subject.Subject;
import org.junit.Test;
public class ShiroTest {@Test
public void testShiro(){//1创建Realm(安全数据源)//通过shiro.ini配置文件创建RealmIniRealm realm=new IniRealm("classpath:shiro.ini");//2创建SecurityManagerDefaultSecurityManager securityManager=new DefaultSecurityManager();//注入创建的Realm(安全数据源)securityManager.setRealm(realm);SecurityUtils.setSecurityManager(securityManager);//3,操作Subject,进行认证Subject subject=SecurityUtils.getSubject();//封装一个令牌UsernamePasswordToken token=new UsernamePasswordToken("admin","123456");try {subject.login(token);} catch (AuthenticationException e) {System.out.println("认证异常");e.printStackTrace();}System.out.println("是否认证通过:"+subject.isAuthenticated());//认证通过后,进行权限验证System.out.println("是否为管理员角色"+subject.hasRole("管理员"));//判断是否为某个角色System.out.println("是否能操作用户查看功能"+subject.isPermitted("user:view"));//判断是否拥有某个权限//也可以使用check方法判断是否拥有某权限,但是失败的情况下会抛出UnauthorizedException异常subject.checkPermission("user:view");}
}
运行结果
18:47:48.757 [main] INFO org.apache.shiro.session.mgt.AbstractValidatingSessionManager -- Enabling session validation scheduler...
是否认证通过:true
是否为管理员角色true
是否能操作用户查看功能true
SpringBoot+Shiro认证:
可以自定义一个Realm,需要继承AuthorizingRealm类,这个类封装了很多方法,并继承自Realm类,我们需要重写下面2个方法:
doGetAuthenticationInfo()方法:获取身份信息
doGetAuthorizationInfo()方法:获取权限信息
package com.bdqn.config;
import com.bdqn.pojo.Right;
import com.bdqn.pojo.Role;
import com.bdqn.pojo.User;
import com.bdqn.service.UserService;
import jakarta.annotation.Resource;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import java.util.Set;
public class MyShiroRealm extends AuthorizingRealm {//安全数据源@Resourceprivate UserService userService;@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {System.out.println("调用MyShiroRealm的doGetAuthenticationInfo获取身份信息");//获得身份信息UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;String usrName = token.getUsername();User user = userService.getUserByUsrName(usrName);if (user == null) {throw new AuthenticationException();//账号错误}if (user.getUsrFlag() == null || user.getUsrFlag().intValue() == 0) {throw new LockedAccountException();//账号被禁用}SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getUsrPassword(),getName());//返回身份信息return info;}@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {System.out.println("调用 MyShiroRealm 的 doGetAuthorizationInfo 获取权限信息");// 获得权限信息User user = (User) principalCollection.getPrimaryPrincipal();SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
// // 静态授权:授予主体(用户)相应的角色和权限
// info.addRole("用户列表");
// if ("管理器".equals(user.getRole().getRoleName())) { // 管理员拥有"增删改"权限
// info.addStringPermission("用户添加");
// info.addStringPermission("用户编辑");
// info.addStringPermission("用户删除");
// }
// System.out.println("为用户 " + user.getUsrName() + " 分配的权限:" + info.getStringPermissions());
// return info;//动态授权Role role = user.getRole();if (role != null) {info.addRole(role.getRoleName());Set<Right> rights = role.getRights();if (rights != null && rights.size() > 0) {for (Right right : rights) {info.addStringPermission(right.getRightCode());}}}return info;}
}
配置Shiro相关对象:
package com.bdqn.config;
import com.bdqn.pojo.Right;
import com.bdqn.service.RoleService;
import jakarta.annotation.Resource;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.mgt.DefaultSecurityManager;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
@Configuration
public class ShiroConfig {@Resourceprivate RoleService roleService;/*** 开启Shiro注解* @returnk*/@Beanpublic DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();advisorAutoProxyCreator.setProxyTargetClass(true);return advisorAutoProxyCreator;}/*** 开启aop注解支持* @return*/@Beanpublic AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();authorizationAttributeSourceAdvisor.setSecurityManager(securityManager);return authorizationAttributeSourceAdvisor;}@Beanpublic MyShiroRealm myShiroRealm() {// 自定义RealmMyShiroRealm myShiroRealm = new MyShiroRealm();return myShiroRealm;}@Beanpublic SecurityManager securityManager(){// 安全管理器SecurityManagerDefaultSecurityManager securityManager=new DefaultSecurityManager();// 注入RealmsecurityManager.setRealm(myShiroRealm());SecurityUtils.setSecurityManager(securityManager);return securityManager;}@Beanpublic ShiroFilterFactoryBean shiroFilterFactory(SecurityManager securityManager){ShiroFilterFactoryBean shiroFilterFactory=new ShiroFilterFactoryBean();// 注入SecurityManagershiroFilterFactory.setSecurityManager(securityManager);// 权限验证:使用Filter控制资源(URL)的访问shiroFilterFactory.setLoginUrl("/login");shiroFilterFactory.setSuccessUrl("/main");shiroFilterFactory.setUnauthorizedUrl("/403");//没有权限跳转403页面Map<String,String> filterChainDefinitionMap=new LinkedHashMap<String,String>();//必须使用LinkHashMap(有序集合)// 配置可以匿名访问的资源(URL):静态资源filterChainDefinitionMap.put("/css/**","anon");filterChainDefinitionMap.put("/fonts/**","anon");filterChainDefinitionMap.put("/images/**","anon");filterChainDefinitionMap.put("/js/**","anon");filterChainDefinitionMap.put("/localcss/**","anon");filterChainDefinitionMap.put("/localjs/**","anon");filterChainDefinitionMap.put("/login","anon");filterChainDefinitionMap.put("/logout","logout");//配置需要特定权限才能访问的资源(URL)//静态授权:包括全部需要特定权限才能访问的资源(URL)filterChainDefinitionMap.put("/user/list","perms[用户列表]");filterChainDefinitionMap.put("/user/add","perms[用户添加]");
// filterChainDefinitionMap.put("/user/edit","perms[用户编辑]");filterChainDefinitionMap.put("/user/del","perms[用户删除");//动态授权List<Right> rights=roleService.findAllRights();for(Right right:rights){if(right.getRightUrl()!=null && !right.getRightUrl().trim().equals("")){filterChainDefinitionMap.put(right.getRightUrl(),"perms["+right.getRightCode()+"]");}}//配置认证访问:其他资源(URL)必须认证通过才能访问;filterChainDefinitionMap.put("/**","authc"); //必须放在过滤器链的最后面shiroFilterFactory.setFilterChainDefinitionMap(filterChainDefinitionMap);return shiroFilterFactory;}
// @Bean(name = "shiroDialect")
// public ShiroDialect shiroDialect(){//thymeleaf页面上使用shiro标签
// return new ShiroDialect();
// }
}
认证流程:
Shiro 是一个强大而灵活的 Java 安全框架,其认证流程主要包括以下步骤:
一、用户发起请求
你向应用程序发起一个需要认证的请求,比如访问一个受保护的页面或调用一个需要特定权限的服务。
二、Subject 被创建
- Shiro 会为当前请求创建一个 Subject 对象。Subject 代表当前 “用户”,可以是实际的用户,也可以是一个服务或系统。
- 这个 Subject 对象通常与当前的安全上下文相关联,包含了关于用户身份和权限的信息。
三、获取 SecurityManager
- Subject 会向 SecurityManager 请求认证和授权服务。
- SecurityManager 是 Shiro 的核心组件,负责管理所有的安全操作。
四、调用 Authenticator
- SecurityManager 将认证任务委托给 Authenticator。
- Authenticator 负责执行实际的认证操作。
五、收集用户提交的凭证
- 如果请求需要认证,通常会要求用户提供用户名和密码等凭证。
- 这些凭证会被收集并传递给 Authenticator 进行验证。
六、执行认证
- Authenticator 会根据配置的认证策略来验证用户提交的凭证。
- 常见的认证策略包括使用数据库、LDAP 目录或其他数据源来验证用户身份。
- 如果认证成功,Authenticator 会返回一个包含用户身份信息的 AuthenticationToken。
七、设置用户身份
- Subject 会接收 AuthenticationToken,并将用户身份设置为已认证状态。
- 此时,Subject 可以代表已认证的用户执行后续的操作。
八、访问控制
- 在用户身份被认证后,Shiro 会根据用户的权限进行访问控制。
- 如果用户试图访问一个受保护的资源,但没有足够的权限,Shiro 会抛出相应的异常或拒绝访问。
总之,Shiro 的认证流程通过 Subject、SecurityManager、Authenticator 等组件的协作,实现了对用户身份的验证和访问控制,确保只有经过认证和授权的用户才能访问受保护的资源。