深入理解Shiro(上)

简介: 深入理解Shiro(上)

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的界面,以及普通用户界面
  • 普通用户只会展示普通用户界面
  • 登录、退出
  • 提示用户名或者密码错误
  • ….


数据库信息展示


shiro001.png


未登录界面展示


shiro002.png


登录及其错误提示

shiro003.png


vip1用户所在页面展示

shiro004.png


普通用户页面展示shiro005.png

目录
相关文章
|
存储 JSON 前端开发
Shiro实现记住我(十)
Shiro实现记住我(十)
428 0
Shiro实现记住我(十)
|
安全 测试技术 API
Shiro详解
Shiro详解
120 0
|
安全 Java 容器
深入理解Shiro(下)
深入理解Shiro(下)
78 0
|
存储 缓存 安全
|
消息中间件 JavaScript 小程序
再见了 shiro
再见了 shiro
|
消息中间件 安全 JavaScript
再见了 shiro !
再见了 shiro !
|
缓存 安全 前端开发
|
Java 数据安全/隐私保护
shiro(二)shiro详解(1)
shiro(二)shiro详解
248 0
shiro(二)shiro详解(1)
|
存储 安全 Java
shiro(二)shiro详解(2)
shiro(二)shiro详解
178 0
shiro(二)shiro详解(2)
|
缓存 安全 Java
Shiro(一):shiro简介
Shiro(一):shiro简介
207 0
Shiro(一):shiro简介