Shiro:自定義Realm實現(xiàn)權限管理方式
Shiro權限管理
1、權限管理
權限管理:不同角色的用戶進入到系統(tǒng)能夠完成的操作是不同的,對不同角色的用戶進行的可執(zhí)行操作的管理稱為權限管理。
2、如何實現(xiàn)權限管理
基于主頁的權限管理:不同的用戶使用不同的主頁,權限通過主頁功能菜單進行限制
基于用戶權限的訪問控制:統(tǒng)權限表、用戶權限表、用戶表,比較冗余
基于用戶角色的訪問控制(RBAC):系統(tǒng)權限表、用戶權限表、用戶表、角色表、用戶角色表
1、基于JavaSe的Shiro的基本使用
1、導入shiro依賴
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-core</artifactId>
<version>1.5.1</version>
</dependency>
但是出現(xiàn)了一點問題:就是引入這個依賴后pom文件就會報錯,可以在pom文件中加入加入阿里云的代理倉庫:
<repositories><!-- 阿里云代碼庫 -->
<repository>
<id>maven-ali</id>
<url>http://maven.aliyun.com/nexus/content/repositories/central</url>
<releases>
<enabled>true</enabled>
</releases>
<snapshots>
<enabled>true</enabled>
<updatePolicy>always</updatePolicy>
<checksumPolicy>fail</checksumPolicy>
</snapshots>
</repository>
</repositories>
2、創(chuàng)建shiro配置文件:shiro.ini
[users] zhangsan=123456,seller lisi=666666,ckmgr admin=222222,admin [roles] admin=* seller=order-add,order-del,order-list ckmgr=ck-add,ck-del,ck-list
3、shiro的基本使用
public class TestShiro {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("請輸入用戶名:");
String username = sc.nextLine();
System.out.println("請輸入密碼:");
String password = sc.nextLine();
//創(chuàng)建安全管理器
DefaultSecurityManager securityManager = new DefaultSecurityManager();
//創(chuàng)建realm
IniRealm realm = new IniRealm("classpath:shiro.ini");
//將realm設置給安全管理器
securityManager.setRealm(realm);
//將realm設置給SecurityUtils工具
SecurityUtils.setSecurityManager(securityManager);
//通過SecurityUtils獲取subject對象
Subject subject = SecurityUtils.getSubject();
//認證流程
UsernamePasswordToken token = new UsernamePasswordToken(username, password);
System.out.println(subject.isAuthenticated());//false
//完成認證
subject.login(token);
System.out.println(subject.isAuthenticated());//true
//授權
//判斷是否有某個角色
subject.hasRole("seller");//true
//判斷是否有某個權限
boolean permitted = subject.isPermitted("oredr-del");
System.out.println(permitted);//true
}
}
4、shiro認證授權流程

(1) 通過subject.login(token)進行登錄,就會將token包含的用戶信息(賬號和密碼)傳遞給SecurityManager
(2) SecurityManager會調用Authentication進行認證
(3) Authentication就會根據(jù)Realm安全信息進行認證校驗
(4) Realm根據(jù)得到的token,調用doGetAuthenticationInfo()方法進行認證
(5) 認證完成后一層層返回到subject
2、SpringBoot整合shiro
- 1、導入shiro依賴:
- 2、配置shiro過濾器:攔截進行認證和授權的用戶
- 3、配置SecurityManager到Spring容器
- 4、配置Realm(SecurityManager需要Realm)
1. 導入依賴
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.1</version>
</dependency>
2. 配置shiro過濾器
/**
* Shiro的配置類
*/
@Configuration
public class ShiroConfig {
//將Realm交給Spring容器創(chuàng)建
@Bean
public IniRealm getRealm() {
IniRealm iniRealm = new IniRealm("classpath:shiro.ini");
return iniRealm;
}
//將DefaultSecurityManager交給Spring容器來創(chuàng)建和管理
@Bean
public DefaultSecurityManager getDefaultSecurityManager(IniRealm iniRealm) {
//SecurityManager要完成認證和校驗需要Realm
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(iniRealm);
return securityManager;
}
//配置shiro的過濾器
@Bean
public ShiroFilterFactoryBean shiroFilter(DefaultSecurityManager securityManager) {
//過濾器工廠
ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
//過濾器是進行權限校驗的核心,進行認證和授權需要SecurityManager
filter.setSecurityManager(securityManager);
//設置攔截規(guī)則
//anon:匿名用戶可以訪問,authc:授權用戶可以訪問
Map<String, String> filterMap = new HashMap<>();
filterMap.put("/","anon"); //項目個根路徑不攔截
filterMap.put("/login.html","anon"); //登錄頁面不攔截
filterMap.put("/register.html","anon"); //注冊頁面不攔截
filterMap.put("/user/login","anon"); //登錄不攔截
filterMap.put("/user/regist","anon"); //注冊不攔截
filterMap.put("/static/**","anon"); //靜態(tài)頁面不攔截
filterMap.put("/**","authc"); //除了上面的請求路徑,其他路徑都要攔截
filter.setFilterChainDefinitionMap(filterMap);
//設置默認的登錄頁面
filter.setLoginUrl("/login.html");
//設置未授權訪問的頁面路徑(一個頁面如果未授權讓其跳轉到登錄頁面)
filter.setUnauthorizedUrl("/login.html");
return filter;
}
}
3. 進行認證測試
1、UserService:
@Service
public class UserService {
public void check(String username,String password){
Subject subject = SecurityUtils.getSubject();
UsernamePasswordToken token = new UsernamePasswordToken(username,password);
subject.login(token);
}
}
2、UserController:
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/login")
public String login(String username,String password){
try {
userService.check(username,password);
System.out.println("登錄成功");
return "index";
} catch (Exception e) {
System.out.println("登錄失敗");
return "login";
}
}
}
3、login.html登錄頁面:
<form action="user/login"> <p>用戶名:<input type="text" name="username"/></p> <p>密碼:<input type="text" name="password"/></p> <p><input type="submit" value="登錄"/></p> </form>
4、shiro.ini配置文件:
[users] zhangsan=123456
5、認證成功:跳到index首頁

6、認證失敗,跳到登錄頁面
3、JdbcRealm實現(xiàn)權限管理

1. JdbcRealm表結構
這些表名和表結構都是固定的不能更改:
用戶信息表:users
create table users(
id int primary key auto_increment,
username varchar(60) not null unique,
password varchar(20) not null,
password_salt varchar(20)
)
insert into users(username,password) values("zhangsan","123456");
insert into users(username,password) values("lisi","123456");
insert into users(username,password) values("wangwu","123456");
insert into users(username,password) values("zhaoliu","123456");
insert into users(username,password) values("chenqi","123456");
角色信息表:user_roles
create table user_roles(
id int primary key auto_increment,
username varchar(60) not null,
role_name varchar(100) not null
)
insert into user_roles(username,role_name) values("zhangsan","admin");
insert into user_roles(username,role_name) values("lisi","cmanager"); -- 庫管人員
insert into user_roles(username,role_name) values("wangwu","xmanager");-- 銷售人員
insert into user_roles(username,role_name) values("zhaoliu","kmanager");-- 客服人員
insert into user_roles(username,role_name) values("chenqi","zmanager"); -- 行政人員
權限信息表:roles_permissions
create table roles_permissions(
id int primary key auto_increment,
role_name varchar(60) not null,
permission varchar(100) not null
)
-- 管理員具備所有權限
insert into roles_permissions(role_name,permission) values("admin","*");
-- 庫管人員
insert into roles_permissions(role_name,permission) values("cmanager","sys:c:save");
insert into roles_permissions(role_name,permission) values("cmanager","sys:c:delete");
insert into roles_permissions(role_name,permission) values("cmanager","sys:c:find");
insert into roles_permissions(role_name,permission) values("cmanager","sys:c:update");
-- 銷售人員
insert into roles_permissions(role_name,permission) values("xmanager","sys:c:save");
insert into roles_permissions(role_name,permission) values("xmanager","sys:x:find");
insert into roles_permissions(role_name,permission) values("xmanager","sys:x:delete");
insert into roles_permissions(role_name,permission) values("xmanager","sys:x:update");
insert into roles_permissions(role_name,permission) values("xmanager","sys:k:save");
insert into roles_permissions(role_name,permission) values("xmanager","sys:k:find");
insert into roles_permissions(role_name,permission) values("xmanager","sys:k:delete");
insert into roles_permissions(role_name,permission) values("xmanager","sys:k:update");
-- 客服人員
insert into roles_permissions(role_name,permission) values("kmanager","sys:k:find");
insert into roles_permissions(role_name,permission) values("kmanager","sys:k:update");
-- 行政人員
insert into roles_permissions(role_name,permission) values("zmanager","sys:k:find");

2. 整合JdbcRealm
1、整合Druid和MyBatis:
# 數(shù)據(jù)庫配置 spring.datasource.druid.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.druid.url=jdbc:mysql://localhost:3306/db_shiro1?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=UTC spring.datasource.druid.username=root spring.datasource.druid.password=root # 連接池配置 #連接池建立時創(chuàng)建的初始化連接數(shù) spring.datasource.druid.initial-size=5 #連接池中最大的活躍連接數(shù) spring.datasource.druid.max-active=20 #連接池中最小的活躍連接數(shù) spring.datasource.druid.min-idle=5 # 配置獲取連接等待超時的時間 spring.datasource.druid.max-wait=60000 # mybatis 配置 mybatis.mapper-locations=classpath:mappers/*Mapper.xml mybatis.type-aliases-package=com.hh.beans
2、導入shiro依賴:
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.1</version>
</dependency>
3、配置shiro過濾器:只需要將IniRealm 更改為JdbcRealm
@Configuration
public class ShiroConfig {
@Bean
public JdbcRealm getJDBCRealm(DataSource dataSource){
JdbcRealm jdbcRealm = new JdbcRealm();
//JdbcRealm會自行從數(shù)據(jù)庫中查詢用戶和權限數(shù)據(jù)(前提是數(shù)據(jù)庫表結構要符合JdbcRealm表結構)
jdbcRealm.setDataSource(dataSource);
//jdbcRealm默認開啟認證功能,如果想要開啟授權功能,需要手動開啟
jdbcRealm.setPermissionsLookupEnabled(true);
return jdbcRealm;
}
//將DefaultSecurityManager交給Spring容器來創(chuàng)建和管理
@Bean
public DefaultSecurityManager getDefaultSecurityManager(JdbcRealm jdbcRealm) {
//SecurityManager要完成認證和校驗需要Realm
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(jdbcRealm);
return securityManager;
}
//配置shiro的過濾器
@Bean
public ShiroFilterFactoryBean shiroFilter(DefaultSecurityManager securityManager) {
//過濾器工廠
ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
//過濾器是進行權限校驗的核心,進行認證和授權需要SecurityManager
filter.setSecurityManager(securityManager);
//設置攔截規(guī)則
//anon:匿名用戶可以訪問,authc:授權用戶可以訪問
Map<String, String> filterMap = new HashMap<>();
filterMap.put("/", "anon"); //項目個根路徑不攔截
filterMap.put("/login.html", "anon"); //登錄頁面不攔截
filterMap.put("/register.html", "anon"); //注冊頁面不攔截
filterMap.put("/user/login", "anon"); //登錄不攔截
filterMap.put("/user/regist", "anon"); //注冊不攔截
filterMap.put("/static/**", "anon"); //靜態(tài)頁面不攔截
filterMap.put("/**", "authc"); //除了上面的請求路徑,其他路徑都要攔截
filter.setFilterChainDefinitionMap(filterMap);
//設置默認的登錄頁面
filter.setLoginUrl("/login.html");
//設置未授權訪問的頁面路徑(一個頁面如果未授權讓其跳轉到登錄頁面)
filter.setUnauthorizedUrl("/login.html");
return filter;
}
}
4、進行認證測試:和上面測試方法相同
由于只要我們按照規(guī)定寫了數(shù)據(jù)庫表結構,那么既可以直接使用數(shù)據(jù)庫中的信息

4、實現(xiàn)前端的權限菜單展示
1. 在Thymeleaf中使用標簽
1、在pom.xml文件中導入thymeleaf模版對shiro標簽支持的依賴
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
2、在ShiroConfig中配置Shiro的方言:
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
3、Thymeleaf模版中引入shiro的命名空間:
<html xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"> ... </html>
2. 常用標簽
2.1 guest
判斷用戶是否是游客身份,如果是游客身份則顯示此標簽內容
<shiro:guest> 歡迎游客,<a href="login.html" rel="external nofollow" rel="external nofollow" >請登錄</a> </shiro:guest>
2.2 user
判斷用戶是否是認證身份,如果是認證身份則顯示此標簽內容
<shiro:user> 已登錄用戶 </shiro:user>

2.3 principal
獲取當前登錄用戶名
<shiro:user> 已登錄用戶<shiro:principal/>歡迎您! </shiro:user>

2.4 hasRole
當期那登錄用戶的角色
<shiro:user> 當前用戶<shiro:principal/>歡迎您! 當前用戶為<shiro:hasRole name="admin">超級管理員</shiro:hasRole> <shiro:hasRole name="cmanager">倉管人員</shiro:hasRole> <shiro:hasRole name="xmanager">銷售人員</shiro:hasRole> <shiro:hasRole name="kmanager">客服人員</shiro:hasRole> <shiro:hasRole name="zmanager">行政人員</shiro:hasRole> </shiro:user>
登錄用戶為zhangsan:

登錄用戶為lisi:

2.5 hasPermission
當前登錄用戶具有的權限
<!DOCTYPE html> <html xmlns:th="http://www.thymeleaf.org" xmlns:shiro="http://www.pollix.at/thymeleaf/shiro"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> <shiro:guest> 歡迎游客,<a href="login.html" rel="external nofollow" rel="external nofollow" >請登錄</a> </shiro:guest> <shiro:user> 當前用戶<shiro:principal/>歡迎您! 當前用戶為<shiro:hasRole name="admin">超級管理員</shiro:hasRole> <shiro:hasRole name="cmanager">倉管人員</shiro:hasRole> <shiro:hasRole name="xmanager">銷售人員</shiro:hasRole> <shiro:hasRole name="kmanager">客服人員</shiro:hasRole> <shiro:hasRole name="zmanager">行政人員</shiro:hasRole> </shiro:user> 倉庫管理: <ul> <shiro:hasPermission name="sys:c:save"><li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >入庫</a> </li></shiro:hasPermission> <shiro:hasPermission name="sys:c:delete"><li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >出庫</a> </li></shiro:hasPermission> <shiro:hasPermission name="sys:c:update"><li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >修改</a> </li></shiro:hasPermission> <shiro:hasPermission name="sys:c:find"><li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >查詢</a> </li></shiro:hasPermission> </ul> 訂單管理: <ul> <shiro:hasPermission name="sys:x:save"><li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >添加訂單</a> </li></shiro:hasPermission> <shiro:hasPermission name="sys:x:delete"><li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >刪除訂單</a> </li></shiro:hasPermission> <shiro:hasPermission name="sys:x:update"><li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >修改訂單</a> </li></shiro:hasPermission> <shiro:hasPermission name="sys:x:find"><li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >查詢訂單</a> </li></shiro:hasPermission> </ul> 客戶管理: <ul> <shiro:hasPermission name="sys:k:save"><li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >添加客戶</a></li></shiro:hasPermission> <shiro:hasPermission name="sys:k:delete"><li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >刪除客戶</a></li></shiro:hasPermission> <shiro:hasPermission name="sys:k:update"><li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >修改客戶</a></li></shiro:hasPermission> <shiro:hasPermission name="sys:k:find"><li><a href="#" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" rel="external nofollow" >查詢客戶</a></li></shiro:hasPermission> </ul> </body> </html>
登錄用戶為:lisi

登錄用戶為zhangsan:

3. 認證流程回顧

5、自定義Realm實現(xiàn)權限管理
1. 表結構的設計
1.1 用戶表:tb_users
create table tb_users(
user_id int primary key auto_increment,
username varchar(60) not null unique,
password varchar(20) not null,
password_salt varchar(60)
);
insert into tb_users(username,password) values("zhangsan","123456");
insert into tb_users(username,password) values("lisi","123456");
insert into tb_users(username,password) values("wangwu","123456");
insert into tb_users(username,password) values("zhaoliu","123456");
insert into tb_users(username,password) values("chenqi","123456");
1.2 角色表:tb_roles
create table tb_roles(
role_id int primary key auto_increment,
role_name varchar(100) not null
);
insert into tb_roles(role_name) values("admin");
insert into tb_roles(role_name) values("cmanager");
insert into tb_roles(role_name) values("xmanager");
insert into tb_roles(role_name) values("kmanager");
insert into tb_roles(role_name) values("zmanager");
1.3 權限表:tb_permissions
create table tb_permissions(
permission_id int primary key auto_increment,
permission_code varchar(20) not null,
permission_name varchar(60)
);
insert into tb_permissions(permission_code,permission_name) values("sys:c:save","入庫");
insert into tb_permissions(permission_code,permission_name) values("sys:c:delete","出庫");
insert into tb_permissions(permission_code,permission_name) values("sys:c:update","修改");
insert into tb_permissions(permission_code,permission_name) values("sys:c:find","查詢");
insert into tb_permissions(permission_code,permission_name) values("sys:x:save","新增訂單");
insert into tb_permissions(permission_code,permission_name) values("sys:x:delete","刪除訂單");
insert into tb_permissions(permission_code,permission_name) values("sys:x:update","修改訂單");
insert into tb_permissions(permission_code,permission_name) values("sys:x:find","查詢訂單");
insert into tb_permissions(permission_code,permission_name) values("sys:k:save","新增客戶");
insert into tb_permissions(permission_code,permission_name) values("sys:k:delete","刪除客戶");
insert into tb_permissions(permission_code,permission_name) values("sys:k:update","修改客戶");
insert into tb_permissions(permission_code,permission_name) values("sys:k:find","查詢客戶");
1.4 用戶角色表:tb_urs
create table tb_urs(
uid int not null,
rid int not null
-- primary key(uid,rid),
-- constraint FK_user foreign key(uid) references tb_users(user_id),
-- constraint FK_role foreign key(rid) references tb_rolls(roll_id)
);
-- zhangsan具有所有角色,代表具有所有權限,不用給他分配權限
insert into tb_urs(uid,rid) values(1,1);-- zhangsan用戶具有admin角色
insert into tb_urs(uid,rid) values(1,2);-- zhangsan用戶具有cmanager角色
insert into tb_urs(uid,rid) values(1,3);-- zhangsan用戶具有xmanager角色
insert into tb_urs(uid,rid) values(1,4);-- zhangsan用戶具有kmanagerr角色
insert into tb_urs(uid,rid) values(1,5);-- zhangsan用戶具有zmanager角色
insert into tb_urs(uid,rid) values(2,2);-- lisi用戶具有cmanager角色
insert into tb_urs(uid,rid) values(3,3);-- wangwu用戶具有xmanager角色
insert into tb_urs(uid,rid) values(4,4);-- zhaoliu用戶具有kmanager角色
insert into tb_urs(uid,rid) values(5,5);-- chenqi用戶具有zmanager角色
1.5 角色權限表:tb_rps
create table tb_rps(
rid int not null,
pid int not null
);
-- 給角色2(倉管)分配權限
insert into tb_rps(rid,pid) values(2,1);
insert into tb_rps(rid,pid) values(2,2);
insert into tb_rps(rid,pid) values(2,3);
insert into tb_rps(rid,pid) values(2,4);
-- 給角色3(銷售)分配權限
insert into tb_rps(rid,pid) values(3,3);
insert into tb_rps(rid,pid) values(3,5);
insert into tb_rps(rid,pid) values(3,6);
insert into tb_rps(rid,pid) values(3,7);
insert into tb_rps(rid,pid) values(3,8);
insert into tb_rps(rid,pid) values(3,9);
insert into tb_rps(rid,pid) values(3,10);
insert into tb_rps(rid,pid) values(3,11);
insert into tb_rps(rid,pid) values(3,12);
-- 給角色4(客服)分配權限
insert into tb_rps(rid,pid) values(4,11);
insert into tb_rps(rid,pid) values(4,12);
-- 給角色5(行政)分配權限
insert into tb_rps(rid,pid) values(5,4);
insert into tb_rps(rid,pid) values(5,8);
insert into tb_rps(rid,pid) values(5,12);
2. Dao層實現(xiàn)

shiro 進行認證需要用戶信息:
- 根據(jù)用戶名查詢用戶信息
shiro進行權限管理需要當前用戶的角色和權限:
- 根據(jù)用戶名查詢當前用戶的角色列表
- 根據(jù)用戶名查詢當前用戶的權限列表
2.1 根據(jù)用戶名查詢用戶信息
實體類User
@Data
public class User {
private String userId;
private String userName;
private String userPwd;
private String pwdSalt;
}
dao接口
@Mapper
public interface UserDao {
//根據(jù)用戶名查詢用戶信息
public User queryUserByUsername(String username) throws Exception;
}
映射配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hh.dao.UserDao">
<resultMap id="userMap" type="User">
<id column="user_id" property="userId"></id>
<result column="username" property="userName"/>
<result column="password" property="userPwd"/>
<result column="password_salt" property="pwdSalt"/>
</resultMap>
<select id="queryUserByUsername" resultMap="userMap">
select * from tb_users
where username=#{username}
</select>
</mapper>
2.2 根據(jù)用戶名查詢角色信息
dao接口
@Mapper
public interface RoleDao {
public Set<String> queryRoleNamesByUsername(String username) throws Exception;
}
映射配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hh.dao.RoleDao">
<select id="queryRoleNamesByUsername" resultSets="java.util.Set" resultType="string">
select
role_name
from
tb_users
join
tb_urs
on
tb_users.user_id = tb_urs.uid
join
tb_roles
on
tb_urs.rid = tb_roles.role_id
where
tb_users.username=#{username}
</select>
</mapper>
2.3 根據(jù)用戶名查詢權限列表
dao接口
public interface PermissionDAO {
public Set<String> queryPermissionsByUsername(String username) throws Exception;
}
映射配置
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.hh.dao.PermissionDao">
<select id="queryPermissionsByUsername" resultSets="java.util.Set" resultType="string">
select
tb_permissions.permission_code
from
tb_users
join
tb_urs
on
tb_users.user_id=tb_urs.uid
join
tb_roles
on
tb_urs.rid=tb_roles.role_id
join
tb_rps
on
tb_roles.role_id=tb_rps.rid
join
tb_permissions
on
tb_rps.pid=tb_permissions.permission_id
where
tb_users.username=#{username}
</select>
</mapper>
3. 整合Shiro
3.1 導入依賴
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.1</version>
</dependency>
<dependency>
<groupId>com.github.theborakompanioni</groupId>
<artifactId>thymeleaf-extras-shiro</artifactId>
<version>2.0.0</version>
</dependency>
3.2 配置Shiro過濾器
@Configuration
public class ShiroConfig {
//1、配置Shiro的方言支持
//2、配置Realm
//3、配置SecurityManager
//4、配置過濾器
@Bean
public ShiroDialect getShiroDialect(){
return new ShiroDialect();
}
//自定義Realm,Realm相當于數(shù)據(jù)源,從數(shù)據(jù)庫中查詢出認證信息和授權信息
@Bean
public MyRealm getRealm(){
MyRealm myRealm = new MyRealm();
return myRealm;
}
@Bean
public DefaultWebSecurityManager getDefaultWebSecurityManager(MyRealm myRealm){
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
securityManager.setRealm(myRealm);
return securityManager;
}
@Bean
public ShiroFilterFactoryBean shiroFilter(DefaultWebSecurityManager securityManager){
ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean();
//過濾器就是shiro就行權限校驗的核心,進行認證和授權是需要SecurityManager的
filter.setSecurityManager(securityManager);
Map<String,String> filterMap = new HashMap<>();
filterMap.put("/","anon");
filterMap.put("/index.html","anon");
filterMap.put("/login.html","anon");
filterMap.put("/regist.html","anon");
filterMap.put("/user/login","anon");
filterMap.put("/user/regist","anon");
filterMap.put("/layui/**","anon");
filterMap.put("/**","authc");
filter.setFilterChainDefinitionMap(filterMap);
filter.setLoginUrl("/login.html");
//設置未授權訪問的頁面路徑()
filter.setUnauthorizedUrl("/login.html");
return filter;
}
}
3.3 自定義Realm
/**
* 自定義Realm的規(guī)范:
* 1、創(chuàng)建一個類實現(xiàn)AuthorizingRealm,重寫里面的兩個方法
* 2、重寫getName()方法,返回當前Realm的自定義名稱
*/
public class MyRealm extends AuthorizingRealm {
@Autowired
private UserDao userDao;
@Autowired
private RoleDao roleDao;
@Autowired
private PermissionDao permissionDao;
public String getName(){
return "myRealm";
}
/**
* 獲取認證信息:將用戶密碼查詢出來交給shiro
* @param authenticationToken token就是傳遞的 subject.login(token)
*/
@SneakyThrows
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
UsernamePasswordToken token = (UsernamePasswordToken) authenticationToken;
//從token中獲取用戶名
String username = token.getUsername();
//根據(jù)用戶名到數(shù)據(jù)庫中查詢用戶信息
User user = userDao.queryUserByUsername(username);
if(user==null){
return null;
}
//將查詢出來的密碼封裝成安全信息給shiro
AuthenticationInfo info = new SimpleAuthenticationInfo(
username,//當前用戶的用戶名
user.getUserPwd(),//從數(shù)據(jù)庫中查詢出來的安全數(shù)據(jù)
getName()
);
return info;
}
/**
* 獲取授權信息:將當前用戶的角色和權限查詢出交給shiro
* @param principalCollection
*/
@SneakyThrows
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
//獲取用戶的用戶名
String username = (String)principalCollection.iterator().next();
//根據(jù)用戶名查詢用戶的角色列表
Set<String> roleNames = roleDao.queryRoleNamesByUsername(username);
//根據(jù)用戶名查詢用戶的權限列表
Set<String> ps = permissionDao.queryPermissionsByUsername(username);
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
info.setRoles(roleNames);
info.setStringPermissions(ps);
return info;
}
}
測試結果:

以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關文章
詳解IDEA 中使用Maven創(chuàng)建項目常見錯誤和使用技巧(推薦)
這篇文章主要介紹了詳解IDEA 中使用Maven創(chuàng)建項目常見錯誤和使用技巧(推薦),本文給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2020-07-07
SpringBoot中使用spring-retry 解決失敗重試調用
本文主要介紹了SpringBoot中使用spring-retry 解決失敗重試調用,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2023-07-07
詳解在IDEA中使用MyBatis Generator逆向工程生成代碼
這篇文章主要介紹了詳解在IDEA中使用MyBatis Generator逆向工程生成代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-06-06
Spring?Cloud?中自定義外部化擴展機制原理及實戰(zhàn)記錄
這篇文章主要介紹了Spring?Cloud?中自定義外部化擴展機制原理及實戰(zhàn),本文通過實例代碼給大家介紹的非常詳細,對大家的學習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-02-02

