1.准备一个web项目
加入web lombok thymeleaf shiro mybatis sqlconnector等支持
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>com.shiro</groupId>
<artifactId>shiro</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>shiro</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<dependencies>
<!--redis-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
<!--thymeleaf-->
<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>
<!--shiro支持-->
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.0</version>
</dependency>
<!--持久层框架mybatis和mysql驱动8.0.9-->
<dependency>
<groupId>org.mybatis.spring.boot</groupId>
<artifactId>mybatis-spring-boot-starter</artifactId>
<version>2.1.1</version>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<scope>runtime</scope>
</dependency>
<!--插件简化代码-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.junit.vintage</groupId>
<artifactId>junit-vintage-engine</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>io.projectreactor</groupId>
<artifactId>reactor-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
**2.自定义一个Realm配置类
- 继承 extends AuthorizingRealm
该配置作用是为了定义你的授权以及认证逻辑.***
public class CustomRealm extends AuthorizingRealm {
//重写两个方法 配置你的内容
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行授权逻辑");
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行认证逻辑");
return null;
}
}
****```3.然后定义你的ShiroConfig****
这个配置是将你的Realm和securityManager安全管理器关联, 然后再将你的securityManager和ShiroFilterFactoryBean关联,并配置拦截url等设置
``
`
`` `@Configuration public class ShiroConfig {
/**
* 创建自定义配置的Realm
*/
@Bean
CustomRealm myRealm() {
return new CustomRealm ( );
}/** * 创建DefaultWebSecurityManager管理器,使它管理自定义的Realm */ @Bean DefaultWebSecurityManager securityManager() { DefaultWebSecurityManager manager = new DefaultWebSecurityManager ( ); manager.setRealm (myRealm ( )); return manager; } /** *创建shiroFilterFactoryBean * 关联一个securityManager ( )管理器 */ @Bean ShiroFilterFactoryBean shiroFilterFactoryBean() { ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean ( ); //设置安全管理器(参数) bean.setSecurityManager (securityManager ( )); bean.setLoginUrl ("/login"); bean.setSuccessUrl ("/index"); bean.setUnauthorizedUrl ("/unauthorizedurl"); //下面添加shiro内置过滤器 Map<String, String> map = new LinkedHashMap<> ( ); //anon无需权限 map.put ("/", "anon"); //必须认证才能访问 map.put ("/**", "authc"); //user:如果使用rememberme功能 可以直接访问 //perms:该资源必须得到资源权限才可以访问 //role:该资源必须得到角色权限才可以访问 bean.setFilterChainDefinitionMap (map); return bean; }
} ```
4.分析Shiro的核心api
Subject: 用户主体(把操作交给SecurityManager)
SecurityManager: 安全管理器(关联Realm)
Realm: Shiro连接数据的桥梁
5.整合(原生的需要写xml,但是spring整合是通过编写配置类简化)
5.1 pom.xml导入依赖,之前的一样 shiro-spring
5.2 自定义Relm:
public class CustomRealm extends AuthorizingRealm {
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
System.out.println("执行授权逻辑");
return null;
}
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
System.out.println("执行认证逻辑");
return null;
}
}
5.3定义你的ShiroConfig,和之前的不一样我要传参式给他们关联
@Configuration
public class ShiroConfig {
/**
* 创建自定义配置的Realm
*/
@Bean(name="CustomRealm")
CustomRealm myRealm() {
return new CustomRealm ( );
}
/**
* 创建DefaultWebSecurityManager管理器,使它管理自定义的Realm
*参数是定义的Realm bean,或者用之前的方式关联
* @Qualifier("CustomRealm")查找bean
*/
@Bean(name="SecurityManager")
DefaultWebSecurityManager securityManager(@Qualifier("CustomRealm") CustomRealm myRealm) {
DefaultWebSecurityManager manager = new DefaultWebSecurityManager ( );
//关联
manager.setRealm (myRealm );
return manager;
}
/**
*创建shiroFilterFactoryBean
* 关联一个securityManager ( )管理器
*这里也可以通过参数注入bean 关联 为了使用上两种不同的方式就不改了
*/
@Bean
ShiroFilterFactoryBean shiroFilterFactoryBean() {
ShiroFilterFactoryBean bean = new ShiroFilterFactoryBean ( );
//设置安全关联器
bean.setSecurityManager (securityManager ( ));
//修改登陆页面,当你拦截没有权限的页面 需要登陆,那么跳转
bean.setLoginUrl ("/login");
//登陆车功后跳转
bean.setSuccessUrl ("/index");
//
bean.setUnauthorizedUrl ("/unauthorizedurl");
Map<String, String> map = new LinkedHashMap<> ( );
//设置首页不拦截,使用anon设置哪些请求不用拦截,
//值得注意的是authc拦截里的url才会拦截,所以应该设置不用拦截的url应该在它里面
//比如拦截的是/user/* 请求 而里面并不是所有的都需要拦截 那么才需要设置 如/user/index,下面的anon就没必要的
map.put ("/index", "anon");
//拦截add和update请求
map.put ("/add", "authc");
map.put ("/update", "authc");
//map.put ("/**", "authc"); 拦截所有请求
//map.put ("/user/**", "authc"); 拦截/user下的所有请求
bean.setFilterChainDefinitionMap (map);
return bean;
}
}
5.4准备 4个页面
login.html (模拟登陆暂时不用写表单) ,add.html(模拟添加) , update.html (模拟更新) ,test.html(首页提供两个跳转到add,update的链接)
controller管理url :
访问/index是没有拦截的,但是点击 test.html(首页)里设置的标签跳转到/add或者/update 由于没有登陆(拦截)会跳转到login里
@Controller
public class UserController {
@GetMapping("/login")
String login() {
return "login";
}
@GetMapping("/index")
String test() {
return "test";
}
@GetMapping("/add")
String add() {
return "add";
}
@GetMapping("/update")
String update() {
return "update";
}
}
5.5测试:
访问首页/index,有两个链接
点击用户添加:
不能访问到add.html
被拦截到了/login请求