Shiro
Shiro介绍
Apache Shiro(发音为“shee-roh”,日语中“城堡”的意思)是一个功能强大且易于使用的 Java 安全框架,可执行身份验证、授权、加密和会话管理,可用于保护任何应用程序 -从命令行应用程序、移动应用程序到最大的 Web 和企业应用程序。
Shiro 提供应用程序安全 API 来执行以下方面(我喜欢将它们称为应用程序安全的 4 个基石):
- 身份验证 - 证明用户身份,通常称为用户“登录”。
- 授权-访问控制
- 密码学 - 保护或隐藏数据免遭窥探
- 会话管理 - 每个用户的时间敏感状态
- Shiro 还支持一些辅助功能,例如 Web 应用程序安全性、单元测试和多线程支持,但这些功能的存在是为了加强上述四个主要问题。
官网QuickStart
1.Tutorial.java
import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.*; import org.apache.shiro.config.IniSecurityManagerFactory; import org.apache.shiro.mgt.SecurityManager; import org.apache.shiro.session.Session; import org.apache.shiro.subject.Subject; import org.apache.shiro.util.Factory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; public class Tutorial { private static final transient Logger log = LoggerFactory.getLogger(Tutorial.class); public static void main(String[] args) { log.info("My First Apache Shiro Application"); Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini"); SecurityManager securityManager = factory.getInstance(); SecurityUtils.setSecurityManager(securityManager); //1. 获取当前的用户对象Subject Subject currentUser = SecurityUtils.getSubject(); // Do some stuff with a Session (no need for a web or EJB container!!!) //2. 通过当前用户拿到session Session session = currentUser.getSession(); session.setAttribute("someKey", "aValue"); String value = (String) session.getAttribute("someKey"); if (value.equals("aValue")) { log.info("Retrieved the correct value! [" + value + "]"); } // let's login the current user so we can check against roles and permissions: //3. 判断当前的用户是被认证 if (!currentUser.isAuthenticated()) { UsernamePasswordToken token = new UsernamePasswordToken("lonestarr", "vespa"); token.setRememberMe(true); //设置记住我 try { currentUser.login(token); //执行了登录操作(暂时看不到 ) } catch (UnknownAccountException uae) { //未知的账户 log.info("There is no user with username of " + token.getPrincipal()); } catch (IncorrectCredentialsException ice) { // log.info("Password for account " + token.getPrincipal() + " was incorrect!"); } catch (LockedAccountException lae) { log.info("The account for username " + token.getPrincipal() + " is locked. " + "Please contact your administrator to unlock it."); } // ... catch more exceptions here (maybe custom ones specific to your application? catch (AuthenticationException ae) { //unexpected condition? error? } } //say who they are: //print their identifying principal (in this case, a username): log.info("User [" + currentUser.getPrincipal() + "] logged in successfully."); //test a role: //4. 测试当前用户是否有角色 if (currentUser.hasRole("schwartz")) { log.info("May the Schwartz be with you!"); } else { log.info("Hello, mere mortal."); } //test a typed permission (not instance-level) //粗粒度 (暂时为止) if (currentUser.isPermitted("lightsaber:wield")) { log.info("You may use a lightsaber ring. Use it wisely."); } else { log.info("Sorry, lightsaber rings are for schwartz masters only."); } //细粒度 /** * 这些权限都是在shiro.ini中的 * admin = * * schwartz = lightsaber:* * goodguy = winnebago:drive:eagle5 */ //是否拥有更高的权限 if (currentUser.isPermitted("winnebago:drive:eagle5")) { log.info("You are permitted to 'drive' the winnebago with license plate (id) 'eagle5'. " + "Here are the keys - have fun!"); } else { log.info("Sorry, you aren't allowed to drive the 'eagle5' winnebago!"); } //all done - log out!注销 currentUser.logout(); //结束 System.exit(0); } }
我们当前使用的shiro很多的用法都可以从QuickStart中了解到
2.shiro.ini
[users] root = secret, admin guest = guest, guest presidentskroob = 12345, president darkhelmet = ludicrousspeed, darklord, schwartz lonestarr = vespa, goodguy, schwartz # ----------------------------------------------------------------------------- # Roles with assigned permissions # roleName = perm1, perm2, ..., permN # ----------------------------------------------------------------------------- [roles] admin = * schwartz = lightsaber:* goodguy = winnebago:drive:eagle5
实现
导入依赖
<!--shiro重点依赖--> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.4.1</version> </dependency> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.1</version> </dependency> <!--shiro 和前端的交互--> <dependency> <groupId>com.github.theborakompanioni</groupId> <artifactId>thymeleaf-extras-shiro</artifactId> <version>2.1.0</version> </dependency> <!--基础开发依赖--> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--sql驱动--> <dependency> <groupId>com.mysql</groupId> <artifactId>mysql-connector-j</artifactId> <version>8.0.32</version> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>2.1.2</version> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> <version>1.2.17</version> </dependency>
项目实现背景介绍
我们日常使用的所有应用程序都存在着很多不安全的问题,为了解决这些问题,我们学习SpringSecurity、shiro等技术,为实现密码安全问题,我们会使用md5,md5盐值加密....一系列操作
在应用程序中,为了更好的盈利,我们会将普通用户和会员用户进行区分,同时,对于两者之间展现的页面,功能也会有所不同。那么如何实现这种不同
本次练习项目就会通过shiro来实现这些操作
功能实现介绍
- 有 vip1身份的用户会展示有关vip1的界面,以及普通用户界面
- 有 vip2身份的用户会展示有关vip1的界面,以及普通用户界面
- 普通用户只会展示普通用户界面
- 登录、退出
- 提示用户名或者密码错误
- ….
数据库信息展示
未登录界面展示
登录及其错误提示
vip1用户所在页面展示
普通用户页面展示