SpringBoot(38) —— SpringBoot整合Shiro环境搭建

    科技2022-07-13  124

    目录

    1.环境搭建2.ShiroConfig3.创建用于测试的页面4.小结


    1.环境搭建

    创建一个SpringBoot项目,就作为父项目springboot-07-shiro的一个子模块创建即可 导入thymeleaf依赖<!--thymeleaf依赖--> <dependency> <groupId>org.thymeleaf</groupId> <artifactId>thymeleaf-spring5</artifactId> </dependency> <dependency> <groupId>org.thymeleaf.extras</groupId> <artifactId>thymeleaf-extras-java8time</artifactId> </dependency> 在template文件夹下创建一个视图,再创建一个controller,用于跳转该视图,主要测试整个项目环境是否搭建成功
    在测试的时候发现了一件很奇怪的事情,本来我在template文件夹下面创建了一个index.html,然后去写了一个controller@Controller public class HelloController { @RequestMapping("/test") public String test(){ return "index"; } } 按照我编写的controller,我需要请求localhost:8080/test才会跳转刚刚创建的index.html,但是当我访问localhost:8080的时候,我就已经进入了index.html,小老弟怎么回事?怎么还默认跳入了?未卜先知?显然不可能,所以我就去查看了springboot自动配置的欢迎页的源码/** * An {@link AbstractUrlHandlerMapping} for an application's welcome page. Supports both * static and templated files. If both a static and templated index page are available, * the static page is preferred. * * @author Andy Wilkinson * @author Bruce Brouwer */ final class WelcomePageHandlerMapping extends AbstractUrlHandlerMapping { private static final Log logger = LogFactory.getLog(WelcomePageHandlerMapping.class); private static final List<MediaType> MEDIA_TYPES_ALL = Collections.singletonList(MediaType.ALL); WelcomePageHandlerMapping(TemplateAvailabilityProviders templateAvailabilityProviders, ApplicationContext applicationContext, Optional<Resource> welcomePage, String staticPathPattern) { if (welcomePage.isPresent() && "/**".equals(staticPathPattern)) { logger.info("Adding welcome page: " + welcomePage.get()); setRootViewName("forward:index.html"); } else if (welcomeTemplateExists(templateAvailabilityProviders, applicationContext)) { logger.info("Adding welcome page template: index"); setRootViewName("index"); } } } 首先注释告诉我们,我们可以使用这个类设置整个项目的欢迎页,欢迎页支持静态文件和模板文件,即我们既可以把我们的欢迎页放在静态文件夹中,又可以放在模板文件夹template中,但是如果静态索引页和模板索引页都可用,则首选静态页然后注意这个类构造,上面源码已经给出 从源码中我们就可以看出,只要我们在静态资源/模板文件夹下创建了一个名为index.html的文件,就会被自动设置为springboot项目的欢迎页,当我们访问localhost:8080的时候就会返回这个页面给我们
    测试环境是否搭建成功

    2.ShiroConfig

    shiro3大对象:Subject(用户)、SecurityManager(管理所有用户)、Realm(连接数据)导入springboot整合shiro的依赖<!--springboot整合shiro的依赖--> <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-spring --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version>1.6.0</version> </dependency> 注意:这个依赖不是springboot本来就有的启动器或依赖,所以版本需要我们自己管理,这里还是按照习惯使用最新的依赖创建一个配置类config,配置类主要用于将3个类装配到spring容器中:realm、DefaultWebSecurityManager、ShiroFilterFactoryBean其中只有realm是需要我们自己去定义的,其他两个都是shiro的类,可以直接使用定义realm类package com.thhh.config; import org.apache.shiro.authc.AuthenticationException; import org.apache.shiro.authc.AuthenticationInfo; import org.apache.shiro.authc.AuthenticationToken; import org.apache.shiro.authz.AuthorizationInfo; import org.apache.shiro.realm.AuthorizingRealm; import org.apache.shiro.subject.PrincipalCollection; public class UserRealm extends AuthorizingRealm { //授权 @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { System.out.println("执行了授权========>doGetAuthorizationInfo"); return null; } //认证 @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { System.out.println("执行了认证========>doGetAuthenticationInfo"); return null; } } 定义realm类的时候需要继承类AuthorizingRealm,这个类是一个抽象类,它有两个方法没有实现doGetAuthorizationInfo()[授权]和doGetAuthenticationInfo()[认证],在上面的实现中,我们只是输出了这个方法执了将定义的realm装配到spring容器中(在config中放入)package com.thhh.config; import org.apache.shiro.spring.web.ShiroFilterFactoryBean; import org.apache.shiro.web.mgt.DefaultWebSecurityManager; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration public class ShiroConfig { //1、装配realm实例到spring容器中 @Bean public UserRealm userRealm(){ return new UserRealm(); } //2、装配DefaultWebSecurityManager实例到spring容器中,DefaultWebSecurityManager需要关联到我们装配到spring容器中的realm实例,所以我们先写了realm @Bean public DefaultWebSecurityManager securityManager(@Qualifier("userRealm") UserRealm userRealm){ DefaultWebSecurityManager manager = new DefaultWebSecurityManager(); manager.setRealm(userRealm); //将我们的realm对象与DefaultWebSecurityManager关联起来 return manager; } //3、装配realm实例到spring容器中 ShiroFilterFactoryBean,这个实例要关联我们装配到spring容器中的DefaultWebSecurityManager实例,所以它最后写 @Bean public ShiroFilterFactoryBean shiroFilterFactoryBean(@Qualifier("securityManager") DefaultWebSecurityManager securityManager){ ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean(); bean.setSecurityManager(securityManager); return bean; } } 注意:上面传递参数的时候我们使用了注解@Qualifier(“spring容器中bean的id”),这在我们将spring自动装配的时候,bytyname和bytetype都不能使用的时候讲过,直接使用注解@Qualifier可以指定spring容器中的哪一个bean实例注入给这个对象的引用在javaconfig中,我们除了使用方法名称作为装配的bean的默认id,还可以通过注解@Bean(name=”这个bean指定的id“)来为装配的bean指定id

    3.创建用于测试的页面

    创建一个user视图文件夹,在该文件夹下创建两个html文件:add.html和update.html,这两个页面用于我们从index.html跳转 在index.html中引入th命名空间,并添加上面两个页面的跳转a标签<!DOCTYPE html> <html lang="en" xmlns:th="http://www.thymeleaf.org"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <h1>首页</h1> <br> <a th:href="@{/user/add}">add</a> <a th:href="@{/user/update}">update</a> </body> </html> 添加跳转视图的controller@RequestMapping("/user/add") public String addPage(){ return "user/add"; } @RequestMapping("/user/update") public String updatePage(){ return "user/update"; } 测试是否能够跳转 测试成功!

    4.小结

    小结一下上面的步骤

    导入springboot整合shiro的依赖编写shiro的两个核心文件:config和realm 对比spring security,使用shiro多写了3个bean,spring security直接在config中配置认证+授权,而shiro在realm中配置认证+授权,并还要使用config向spring容器中注入3个bean(realm、DefaultWebSecurityManager、ShiroFilterFactoryBean)这样对比下来使用shiro实现认证+授权成本更大
    Processed: 0.018, SQL: 8