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請求