SpringBoot(36) —— Shiro快速开始


1.什么是Shiro

  • Apache Shiro 是 Java 的一个安全(权限)框架
  • Shiro 可以非常容易的开发出足够好的应用,其不仅可以用在 JavaSE 环境,也可以用在 JavaEE 环境
  • Shiro 可以完成:认证、授权、加密、会话管理、与Web 集成、缓存等
  • 下载地址
  • 直接取GitHub上下载压缩包即可
    在这里插入图片描述

2.Shiro的作用

在这里插入图片描述

  • Authentication:身份认证/登录,验证用户是不是拥有相应的身份
  • Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限;即判断用户是否能进行什么操作,如:验证某个用户是否拥有某个角色。或者细粒度的验证某个用户对某个资源是否具有某个权限
  • Session Management:会话管理,即用户登录后就是一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通JavaSE环境,也可以是Web 环境的
  • Cryptography:加密,保护数据的安全性,如密码加密存储到数据库,而不是明文存储
  • Web Support:Web 支持,可以非常容易的集成到Web 环境
  • Caching:缓存,比如用户登录后,其用户信息、拥有的角色/权限不必每次去查,这样可以提高效率
  • Concurrency:Shiro支持多线程应用的并发验证,即如在一个线程中开启另一个线程,能把权限自动传播过去
  • Testing:提供测试支持
  • “Run As”:允许一个用户假装为另一个用户(如果他们允许)的身份进行访问
  • Remember Me:记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了

3.Shiro架构(外部)

    从外部来看Shiro,即从应用程序角度的来观察如何使用Shiro完成工作
在这里插入图片描述

  • Subject:应用代码直接交互的对象是Subject,也就是说Shiro的对外API 核心就是Subject。Subject 代表了当前“用户”,这个用户不一定是一个具体的人,与当前应用交互的任何东西都是Subject,如网络爬虫,机器人等;与Subject 的所有交互都会委托给SecurityManager;Subject 其实是一个门面,SecurityManager才是实际的执行者

  • SecurityManager:安全管理器;即所有与安全有关的操作都会与SecurityManager交互;且其管理着所有Subject;可以看出它是Shiro的核心,它负责与Shiro的其他组件进行交互,它相当于SpringMVC中DispatcherServlet的角色

  • Realm:Shiro从Realm 获取安全数据(如用户、角色、权限),就是说SecurityManager要验证用户身份,那么它需要从Realm 获取相应的用户进行比较以确定用户身份是否合法;也需要从Realm 得到用户相应的角色/权限进行验证用户是否能进行操作;可以把Realm 看成DataSource


4.Shiro架构(内部)

在这里插入图片描述

  • Subject:任何可以与应用交互的“用户”;
  • SecurityManager:相当于SpringMVC中的DispatcherServlet;是Shiro的心脏;所有具体的交互都通过- SecurityManager进行控制;它管理着所有Subject、且负责进行认证、授权、会话及缓存的管理
  • Authenticator:负责Subject 认证,是一个扩展点,可以自定义实现;可以使用认证策略(Authentication Strategy),即什么情况下算用户认证通过了
  • Authorizer:授权器、即访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能
  • Realm:可以有1 个或多个Realm,可以认为是安全实体数据源,即用于获取安全实体的;可以是JDBC 实现,也可以是内存实现等等;由用户提供;所以一般在应用中都需要实现自己的Realm
  • SessionManager:管理Session 生命周期的组件;而Shiro并不仅仅可以用在Web 环境,也可以用在如普通的JavaSE环境
  • CacheManager:缓存控制器,来管理如用户、角色、权限等的缓存的;因为这些数据基本上很少改变,放到缓存中后可以提高访问的性能
  • Cryptography:密码模块,Shiro提高了一些常见的加密组件用于如密码加密/解密

5.Hello World

- 解压下载的压缩文件

  • 按照官方doc只是,下载压缩包之后解压,并进入对应的文件夹
    在这里插入图片描述
  • 创建一个普通的maven项目:springboot-07-shiro
  • 老规矩:删除没有文件夹,把这个项目作为一个父项目,在它内部创建子model
  • 创建子model:hello-shiro
  • 直接打开例子中的pom.xml,将依赖导入子model,注意:按照使用最新版本原则,直接粘贴对应依赖去maven仓库中搜最新的,下面的都是最新的
    <build>
        <plugins>
            <plugin>
                <groupId>org.codehaus.mojo</groupId>
                <artifactId>exec-maven-plugin</artifactId>
                <version>1.6.0</version>
                <executions>
                    <execution>
                        <goals>
                            <goal>java</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <classpathScope>test</classpathScope>
                    <mainClass>Quickstart</mainClass>
                </configuration>
            </plugin>
        </plugins>
    </build>
    
    
    <dependencies>
        <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-core -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-core</artifactId>
            <version>1.6.0</version>
        </dependency>
    
    
        <!-- https://mvnrepository.com/artifact/org.slf4j/jcl-over-slf4j -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>jcl-over-slf4j</artifactId>
            <version>2.0.0-alpha1</version>
        </dependency>
    
        <!-- https://mvnrepository.com/artifact/org.slf4j/slf4j-log4j12 -->
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
            <version>2.0.0-alpha1</version>
        </dependency>
    
        <dependency>
            <groupId>log4j</groupId>
            <artifactId>log4j</artifactId>
            <version>1.2.17</version>
        </dependency>
    </dependencies>
    
  • 拷贝快速开始例子的resource下的资源文件
  • log4j.properties
    log4j.rootLogger=INFO, stdout
    
    log4j.appender.stdout=org.apache.log4j.ConsoleAppender
    log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
    log4j.appender.stdout.layout.ConversionPattern=%d %p [%c] - %m %n
    
    # General Apache libraries
    log4j.logger.org.apache=WARN
    
    # Spring
    log4j.logger.org.springframework=WARN
    
    # Default Shiro logging
    log4j.logger.org.apache.shiro=INFO
    
    # Disable verbose logging
    log4j.logger.org.apache.shiro.util.ThreadContext=WARN
    log4j.logger.org.apache.shiro.cache.ehcache.EhCache=WARN
    
  • shiro.ini
    [users]
    # user 'root' with password 'secret' and the 'admin' role
    root = secret, admin
    # user 'guest' with the password 'guest' and the 'guest' role
    guest = guest, guest
    # user 'presidentskroob' with password '12345' ("That's the same combination on
    # my luggage!!!" ;)), and role 'president'
    presidentskroob = 12345, president
    # user 'darkhelmet' with password 'ludicrousspeed' and roles 'darklord' and 'schwartz'
    darkhelmet = ludicrousspeed, darklord, schwartz
    # user 'lonestarr' with password 'vespa' and roles 'goodguy' and 'schwartz'
    lonestarr = vespa, goodguy, schwartz
    
    # -----------------------------------------------------------------------------
    # Roles with assigned permissions
    # 
    # Each line conforms to the format defined in the
    # org.apache.shiro.realm.text.TextConfigurationRealm#setRoleDefinitions JavaDoc
    # -----------------------------------------------------------------------------
    [roles]
    # 'admin' role has all permissions, indicated by the wildcard '*'
    admin = *
    # The 'schwartz' role can do anything (*) with any lightsaber:
    schwartz = lightsaber:*
    # The 'goodguy' role is allowed to 'drive' (action) the winnebago (type) with
    # license plate 'eagle5' (instance specific id)
    goodguy = winnebago:drive:eagle5
    
  • 拷贝Java代码,文件Quickstart.java
    /*
     * Licensed to the Apache Software Foundation (ASF) under one
     * or more contributor license agreements.  See the NOTICE file
     * distributed with this work for additional information
     * regarding copyright ownership.  The ASF licenses this file
     * to you under the Apache License, Version 2.0 (the
     * "License"); you may not use this file except in compliance
     * with the License.  You may obtain a copy of the License at
     *
     *     http://www.apache.org/licenses/LICENSE-2.0
     *
     * Unless required by applicable law or agreed to in writing,
     * software distributed under the License is distributed on an
     * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
     * KIND, either express or implied.  See the License for the
     * specific language governing permissions and limitations
     * under the License.
     */
    
    import org.apache.shiro.SecurityUtils;
    import org.apache.shiro.authc.*;
    import org.apache.shiro.ini.IniSecurityManagerFactory;
    import org.apache.shiro.mgt.SecurityManager;
    import org.apache.shiro.session.Session;
    import org.apache.shiro.subject.Subject;
    import org.apache.shiro.lang.util.Factory;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    
    /**
     * Simple Quickstart application showing how to use Shiro's API.
     *
     * @since 0.9 RC2
     */
    public class Quickstart {
    
        private static final transient Logger log = LoggerFactory.getLogger(Quickstart.class);
    
    
        public static void main(String[] args) {
    
            // The easiest way to create a Shiro SecurityManager with configured
            // realms, users, roles and permissions is to use the simple INI config.
            // We'll do that by using a factory that can ingest a .ini file and
            // return a SecurityManager instance:
    
            // Use the shiro.ini file at the root of the classpath
            // (file: and url: prefixes load from files and urls respectively):
            Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
            SecurityManager securityManager = factory.getInstance();
    
            // for this simple example quickstart, make the SecurityManager
            // accessible as a JVM singleton.  Most applications wouldn't do this
            // and instead rely on their container configuration or web.xml for
            // webapps.  That is outside the scope of this simple quickstart, so
            // we'll just do the bare minimum so you can continue to get a feel
            // for things.
            SecurityUtils.setSecurityManager(securityManager);
    
            // Now that a simple Shiro environment is set up, let's see what you can do:
    
            // get the currently executing user:
            Subject currentUser = SecurityUtils.getSubject();
    
            // Do some stuff with a Session (no need for a web or EJB container!!!)
            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:
            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:
            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.");
            }
    
            //a (very powerful) Instance Level permission:
            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);
        }
    }
    
  • 测试
  • 这里出现了第一个坑:IniSecurityManagerFactory已经过期,不能使用了,我在项目中连jar包都导入不进来
  • 【解决方法1】将下面这3行代码更换为
    Factory<SecurityManager> factory = new IniSecurityManagerFactory("classpath:shiro.ini");
    SecurityManager securityManager = factory.getInstance();
    SecurityUtils.setSecurityManager(securityManager);
    
    这4行代码
        DefaultSecurityManager factory = new DefaultSecurityManager();
        IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
        factory.setRealm(iniRealm);
        SecurityUtils.setSecurityManager(factory);
    
    再次运行
    在这里插入图片描述
  • 【解决方法2】将原本的出错的import删除,自己手动导入,好处就是不用修改代码,动动手导入类即可
    测试
    在这里插入图片描述
    测试成功!

6.小结

第一个Shiro程序运行成功总共分5步

  • 下载Shiro
  • 创建项目,导入pom依赖【当然,按照一贯使用最新的原则,直接去maven上面找对应的依赖即可】
  • 粘贴Quickstart中的配置文件,两个:log4j.properties+shiro.ini
  • 粘贴Quickstart.java代码【这里注意一下Quickstart中两个import有错误,直接删除自己导入即可】
  • 运行测试
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Spring Boot 是一个非常流行的 Java 开发框架,而 Shiro 则是一个轻量级的身份验证和授权框架。使用 Spring BootShiro 结合起来进行权限管理,可以非常方便地实现用户登录、权限验证等功能。 具体来说,我们可以通过在 Spring Boot 中配置 Shiro,来实现基于角色或权限的访问控制。通过使用 Shiro 提供的 Subject、Realm 等核心组件,我们可以轻松地完成用户身份认证、权限验证等操作。此外,Shiro 还提供了诸如密码加密、会话管理等功能,可以帮助我们更好地保护应用程序的安全性。 总的来说,结合 Spring BootShiro 进行权限管理可以让我们更快速、更安全地开发应用程序。 ### 回答2: Spring Boot 是一种基于 Spring 框架的、用于快速构建应用程序的微服务框架,它可以轻松集成第三方组件,并且提供了一些便利的注解,让开发者可以更加专注于业务逻辑的实现。 而 Shiro 则是一种强大的 Java 安全框架,提供了身份验证、授权、加密等安全功能。Shiro 可以轻松地与 Spring Boot 进行集成,实现 permission-based access control(基于权限的访问控制),这意味着用户必须拥有特定的权限才能访问某些特定的资源。下面我们将详细讨论如何在 Spring Boot 中使用 Shiro 实现权限管理。 1. 添加 Shiro 依赖 首先需要在 Spring Boot 项目中添加 Shiro 的依赖。在 Maven 中,您需要将以下依赖添加到您的 pom.xml 文件中: ``` <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.4.2</version> </dependency> ``` 2. 配置 ShiroSpring Boot 应用程序中,需要创建一个 ShiroFilterFactoryBean 和一个 SecurityManager bean。在 Shiro 过滤器工厂中,您需要指定访问控制规则以及 URL 的映射。这个过程可以通过编写 Shiro 配置文件来完成。下面是一个配置文件的示例。 ``` # shiro.ini [users] # 用户名 = 密码,角色1,角色2,角色3 admin = password, admin user = password, user [roles] # 角色定义 admin = * user = user:read [urls] # url 映射到角色 /login = anon /logout = logout /user/** = user /admin/** = admin ``` 3. 创建控制器 通过将 Shiro 的注解添加到控制器方法中,实现基于角色的访问控制。下面是一个示例控制器: ``` import org.apache.shiro.SecurityUtils; import org.apache.shiro.authc.UsernamePasswordToken; import org.apache.shiro.subject.Subject; import org.springframework.stereotype.Controller; import org.springframework.ui.Model; import org.springframework.web.bind.annotation.GetMapping; @Controller public class UserController { @GetMapping("/user") public String user(Model model) { Subject subject = SecurityUtils.getSubject(); model.addAttribute("user", subject.getPrincipal()); return "user"; } @GetMapping("/admin") public String admin(Model model) { Subject subject = SecurityUtils.getSubject(); model.addAttribute("user", subject.getPrincipal()); return "admin"; } } ``` 在上面的示例中,user 和 admin 控制器方法都是基于角色进行访问控制。只有角色为 user 的用户才能访问 /user 路径,而只有角色为 admin 的用户才能访问 /admin 路径。 4. 创建登录页面 用户需要先登录才能访问有限资源。当用户访问有限资源时,Shiro 触发登录请求并将用户重定向到登录页面。下面是一个示例的登录页面。 ``` <form action="/login" method="POST"> <input type="text" name="username" placeholder="Username" required /> <input type="password" name="password" placeholder="Password" required /> <button type="submit">Login</button> </form> ``` 上面的登录表单将用户名和密码提交到 /login 接口,接口用于验证用户凭证及权限,并且在成功验证后重定向用户到其一开始请求的资源。若没有授权,则会将用户重定向到未授权的页面。 5. 对密码进行加密 在生产环境中,密码必须加密,以避免用户数据泄漏问题。下面是使用 Shiro 进行密码加密的示例代码: ``` import org.apache.shiro.crypto.hash.Md5Hash; import org.apache.shiro.crypto.hash.Sha256Hash; import org.apache.shiro.crypto.hash.SimpleHash; import org.apache.shiro.util.ByteSource; public class PasswordUtil { public static String md5(String password, String salt) { return new Md5Hash(password, ByteSource.Util.bytes(salt), 2).toHex(); } public static String sha256(String password, String salt) { return new Sha256Hash(password, ByteSource.Util.bytes(salt), 1024).toHex(); } public static String simpleHash(String password, String salt) { return new SimpleHash("SHA-3-256", password, ByteSource.Util.bytes(salt), 1024).toString(); } } ``` 在上面的示例中,我们使用了三种不同类型的散列算法——MD5、SHA256 和 SHA-3-256。Shiro 使用 ByteSource 工具类来指明盐值。 在总结一下,Spring BootShiro 的结合可以帮助我们快速构建一个安全可靠的 Web 应用程序,并且通过角色授权方式,可以防止非授权访问尝试。以上就是采用 Spring BootShiro 实现权限管理的基本介绍。 ### 回答3: SpringBoot是一个用于创建基于Spring框架的Java应用程序的工具,它可以让开发人员更轻松地快速创建应用程序。而Shiro是一个强大而灵活的用于认证,授权和会话管理的Java框架。在SpringBoot中集成Shiro可以非常方便地完成权限管理。 Shiro具有许多功能,其中包括身份验证(Authentication)和授权(Authorization),这意味着Shiro可以处理登录和控制用户访问资源。Shiro还支持会话管理,在Web应用程序中可以使用Shiro管理会话,防止会话劫持和防止跨站点脚本攻击。Shiro的另一个优点是可以对加密和散列数据进行简单但强大的支持。此外,使用Shiro可以实现单点登录(Single sign-on,简称SSO),这对企业应用程序非常重要。 在SpringBoot中,集成Shiro非常容易。我们只需要在pom.xml中添加相应的依赖,然后在配置文件中设置Shiro的相关配置即可。配置Shiro认证和授权的最佳实践是将其分开,这样我们可以将认证设置单独控制,并在需要时轻松地将授权设置组合起来。如果我们需要更多的功能,Shiro通常提供了许多可插拔的组件和扩展。 在权限管理方面,Shiro非常适合企业应用程序,可以使用Shiro控制用户对资源的访问权限。我们可以为每个用户或角色设置权限,这就意味着我们可以非常细致地控制资源的访问权限。Shiro提供了各种各样的过滤器,我们可以使用这些过滤器在开发应用程序时精确地控制哪些用户可以访问哪些资源。 总之,SpringBootShiro的集成可以帮助开发人员快速而轻松地构建功能强大的企业应用程序,实现身份验证,授权和会话管理等功能。Shiro的权限管理功能使得我们可以非常精确地控制用户对资源的访问权限,从而满足企业应用程序的需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值