本文共 11423 字,大约阅读时间需要 38 分钟。
Apache Shiro(日语“堡垒(Castle)”的意思)是一个强大易用的Java安全框架,
提供了认证、授权、加密和会话管理功能,可为任何应用提供安全保障 - 从命令行应用、移动应用到大型网络及企业应用。 Apache Shiro 是一个强大而灵活的开源安全框架,它干净利落地处理身份认证,授权,企业会话管理和加密。 Apache Shiro 的首要目标是易于使用和理解。安全有时候是很复杂的,甚至是痛苦的,但它没有必要这样。框架应该尽可能掩盖复杂的地方,露出一个干净而直观的 API,来简化开发人员在使他们的应用程序安全上的努力。以下是你可以用 Apache Shiro 所做的事情: 验证用户来核实他们的身份 对用户执行访问控制,如: 判断用户是否被分配了一个确定的安全角色 判断用户是否被允许做某事 在任何环境下使用 Session API,即使没有 Web 或 EJB 容器。 在身份验证,访问控制期间或在会话的生命周期,对事件作出反应。 聚集一个或多个用户安全数据的数据源,并作为一个单一的复合用户“视图”。 启用单点登录(SSO)功能。 为没有关联到登录的用户启用"Remember Me"服务 … 以及更多——全部集成到紧密结合的易于使用的 API 中。 Shiro 视图在所有应用程序环境下实现这些目标——从最简单的命令行应用程序到最大的企业应用,不强制依赖其他第三方框架,容器,或应用服务器。当然,该项目的目标是尽可能地融入到这些环境,但它能够在任何环境下立即可用。
- Subject:主体,可以看到主体可以是任何与应用交互的“用户”。 2. SecurityManager:相当于 SpringMVC 中的 DispatcherServlet 或者 Struts2 中的FilterDispatcher。它是 Shiro 的核心,所有具体的交互都通过 SecurityManager 进行控制。它管理着所有 Subject、且负责进行认证和授权、及会话、缓存的管理。 3. Authenticator:认证器,负责主体认证的,这是一个扩展点,如果用户觉得 Shiro 默认的不好,我们可以自定义实现。其需要认证策略(Authentication Strategy),即什么情况下算用户认证通过了。 4. Authrizer:授权器,或者访问控制器。它用来决定主体是否有权限进行相应的操作,即控制着用户能访问应用中的哪些功能。 5. Realm:可以有1个或多个 Realm,可以认为是安全实体数据源,即用于获取安全实体的。它可以是 JDBC 实现,也可以是 LDAP 实现,或者内存实现等。 6. SessionManager:如果写过 Servlet 就应该知道 Session 的概念,Session 需要有人去管理它的生命周期,这个组件就是 SessionManager。而 Shiro 并不仅仅可以用在 Web 环境,也可以用在如普通的 JavaSE 环境。 7. SessionDAO:DAO 大家都用过,数据访问对象,用于会话的 CRUD。我们可以自定义 SessionDAO 的实现,控制 session 存储的位置。如通过 JDBC 写到数据库或通过 jedis 写入 redis 中。另外 SessionDAO 中可以使用 Cache 进行缓存,以提高性能。 8. CacheManager:缓存管理器。它来管理如用户、角色、权限等的缓存的。因为这些数据基本上很少去改变,放到缓存中后可以提高访问的性能。 9. Cryptography:密码模块,Shiro 提高了一些常见的加密组件用于如密码加密/解密的
4.0.0 org.springframework.boot spring-boot-starter-parent 2.0.3.RELEASE com.wo shiro_test 1.0-SNAPSHOT org.springframework.boot spring-boot-starter-web org.springframework.boot spring-boot-starter-test test org.projectlombok lombok true mysql mysql-connector-java org.mybatis.spring.boot mybatis-spring-boot-starter 1.1.1 org.apache.shiro shiro-spring 1.4.0
spring: datasource: driver-class-name: com.mysql.jdbc.Driver username: root password: 123456 url: jdbc:mysql://localhost:3306/test4?useUnicode=true&characterEncoding=utf8&useSSL=falsemybatis: mapper-locations: classpath:mapper/*Mapper.xml
[users]zhangsan=123lisi=123
@RunWith(SpringRunner.class)@SpringBootTestpublic class TestShiro { @Test public void testFirstShiro(){ //使用IniSecurityManagerFactory加载shiro_first.ini文件 IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro_first.ini"); //使用工厂类创建securityManager SecurityManager securityManager = iniSecurityManagerFactory.createInstance(); //使用shiro提供的工具类来创建manager的运行环境 SecurityUtils.setSecurityManager(securityManager); //使用工具类获取我们的主体部分 Subject subject = SecurityUtils.getSubject(); //设置用户名及密码部分 //前端用户传输的用户名和密码 UsernamePasswordToken token = new UsernamePasswordToken("lisi", "123"); //从主题中开始登录 try { subject.login(token); System.out.println("用户登录成功!!!!!!!!"); }catch (IncorrectCredentialsException inc){ System.out.println("用户登录失败!!!!!!!!!失败原因 密码错误!!!"); }catch (UnknownAccountException uae){ System.out.println("用户登录失败!!!!!!!!失败原因,没有该用户名"); } if(subject.isAuthenticated()){ System.out.println("验证通过"); }else{ System.out.println("验证失败"); } }}
[users]normal=123,role1admin=admin,role2root=root,role3[roles]role1=user:selectrole2=user:select,user:updaterole3=user:creat,user:delete,user:select,user:update
@RunWith(SpringRunner.class)@SpringBootTestpublic class TestShiroPermissions { @Test public void testUserPermissions(){ //使用IniSecurityManagerFactory加载shiro_first.ini文件 IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro_permission.ini"); //使用工厂类创建securityManager SecurityManager securityManager = iniSecurityManagerFactory.createInstance(); //使用shiro提供的工具类来创建manager的运行环境 SecurityUtils.setSecurityManager(securityManager); //使用工具类获取我们的主体部分 Subject subject = SecurityUtils.getSubject(); //设置用户名及密码部分 //前端用户传输的用户名和密码 UsernamePasswordToken token = new UsernamePasswordToken("root", "root"); //从主题中开始登录 try { subject.login(token); System.out.println("用户登录成功!!!!!!!!"); }catch (IncorrectCredentialsException inc){ System.out.println("用户登录失败!!!!!!!!!失败原因 密码错误!!!"); }catch (UnknownAccountException uae){ System.out.println("用户登录失败!!!!!!!!失败原因,没有该用户名"); } //判断用户的角色 String rol="role2"; boolean hasRole = subject.hasRole(rol); if(hasRole){ System.out.println("用户拥有"+rol+"角色"); }else { System.out.println("用户没有"+rol+"角色"); } //判断用户权限 String per="user:delete"; boolean b = subject.isPermitted(per); if (b){ System.out.println("用户拥有"+per+"权限"); }else { System.out.println("用户没有"+per+"权限"); } //批量验证该用户的角色 boolean[] hasRoles = subject.hasRoles(Arrays.asList("role1", "role2", "role3")); System.out.println(Arrays.toString(hasRoles)); //批量验证该用户的权限 boolean[] permitted = subject.isPermitted("user:creat", "user:delete"); System.out.println(Arrays.toString(permitted)); //验证用户是否拥有输入的全部权限 boolean permittedAll = subject.isPermittedAll("user:creat", "user:delete"); System.out.println(permittedAll); }}
[main]#自定义realmmyrealm=com.wo.shiro.MyRealm#在shiro核心中,设置自定义myrealmsecurityManager.realms=$myrealm
public class MyRealm extends AuthorizingRealm { //授权的方法 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { //获取到前端传输的用户名 String username = (String) principals.getPrimaryPrincipal(); //使用前端传输用户名5表联查,获取到用户的所拥有的权限信息 HashSetobjects=new HashSet<>(); objects.add("user:create"); objects.add("user:update"); //声明simpleAuthorizationInfo 对象 SimpleAuthorizationInfo simpleAuthorizationInfo = new SimpleAuthorizationInfo(); //将权限放置到声明simpleAuthorizationInfo 对象中 simpleAuthorizationInfo.setStringPermissions(objects); //放置角色 simpleAuthorizationInfo.addRole("role1"); return simpleAuthorizationInfo; } //认证的方法 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { //获取到前端传输的用户名 String username = (String) token.getPrincipal(); //使用前端用户名去数据库查询正确的密码 String password="123"; //将前端传输过来的用户名,以及使用该用户名 查询到的正确密码放置到查询出的正确密码放置到simpleAuthticationinfo中进行返回 SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, getName()); return simpleAuthenticationInfo; }}
@RunWith(SpringRunner.class)@SpringBootTestpublic class TestShiroMyRealm { @Test public void testMyRealm(){ //使用IniSecurityManagerFactory加载shiro_first.ini文件 IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro_myrealm.ini"); //使用工厂类创建securityManager SecurityManager securityManager = iniSecurityManagerFactory.createInstance(); //使用shiro提供的工具类来创建manager的运行环境 SecurityUtils.setSecurityManager(securityManager); //使用工具类获取我们的主体部分 Subject subject = SecurityUtils.getSubject(); //设置用户名及密码部分 //前端用户传输的用户名和密码 UsernamePasswordToken token = new UsernamePasswordToken("root", "123"); //从主题中开始登录 try { subject.login(token); System.out.println("用户登录成功"); }catch (IncorrectCredentialsException ex){ System.out.println("用户登录失败,失败原因:密码错误"); } boolean b = subject.hasRole("role2"); if (b){ System.out.println("用户拥有该角色"); }else { System.out.println("用户没有该角色"); } boolean permitted = subject.isPermitted("user:create"); if (permitted){ System.out.println("用户拥有该权限"); }else { System.out.println("用户没有该权限"); } }}
[main]#定义凭证匹配器credentialsMatcher=org.apache.shiro.authc.credential.HashedCredentialsMatcher#设置散列算法credentialsMatcher.hashAlgorithmName=md5#设置散列次数credentialsMatcher.hashIterations=1#将凭证匹配器设置到realmmyRealm=com.wo.shiro.MyRealmMD5myRealm.credentialsMatcher=$credentialsMatchersecurityManager.realms=$myRealm
public class MyRealmMD5 extends AuthorizingRealm{ //权限 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { return null; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { String username = (String) token.getPrincipal(); //用username 去数据库获取加密后的密码 202cb962ac59075b964b07152d234b70 String password="202cb962ac59075b964b07152d234b70"; SimpleAuthenticationInfo simpleAuthenticationInfo = new SimpleAuthenticationInfo(username, password, getName()); return simpleAuthenticationInfo; }}
@RunWith(SpringRunner.class)@SpringBootTestpublic class TestShiroMd5MyRealm { @Test public void testMd5(){ //使用IniSecurityManagerFactory加载shiro_first.ini文件 IniSecurityManagerFactory iniSecurityManagerFactory = new IniSecurityManagerFactory("classpath:shiro_myrealmMd5.ini"); //使用工厂类创建securityManager SecurityManager securityManager = iniSecurityManagerFactory.createInstance(); //使用shiro提供的工具类来创建manager的运行环境 SecurityUtils.setSecurityManager(securityManager); //使用工具类获取我们的主体部分 Subject subject = SecurityUtils.getSubject(); String username = "zhangsan"; String password = "123"; UsernamePasswordToken token = new UsernamePasswordToken(username, password); try { subject.login(token); System.out.println("用户登录成功"); }catch (IncorrectCredentialsException inc){ System.out.println("用户登录失败"); } }}
转载地址:http://icezi.baihongyu.com/