目录
1.环境搭建2.ShiroConfig3.创建用于测试的页面4.小结
1.环境搭建
创建一个SpringBoot项目,就作为父项目springboot-07-shiro的一个子模块创建即可 导入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自动配置的欢迎页的源码
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的依赖
<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 {
@Bean
public UserRealm
userRealm(){
return new UserRealm();
}
@Bean
public DefaultWebSecurityManager
securityManager(@Qualifier("userRealm") UserRealm userRealm
){
DefaultWebSecurityManager manager
= new DefaultWebSecurityManager();
manager
.setRealm(userRealm
);
return manager
;
}
@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实现认证+授权成本更大