Shiro:自定義Realm實(shí)現(xiàn)權(quán)限管理方式
Shiro權(quán)限管理
1、權(quán)限管理
權(quán)限管理:不同角色的用戶進(jìn)入到系統(tǒng)能夠完成的操作是不同的,對(duì)不同角色的用戶進(jìn)行的可執(zhí)行操作的管理稱為權(quán)限管理。
2、如何實(shí)現(xiàn)權(quán)限管理
基于主頁(yè)的權(quán)限管理:不同的用戶使用不同的主頁(yè),權(quán)限通過主頁(yè)功能菜單進(jìn)行限制
基于用戶權(quán)限的訪問控制:統(tǒng)權(quán)限表、用戶權(quán)限表、用戶表,比較冗余
基于用戶角色的訪問控制(RBAC):系統(tǒng)權(quán)限表、用戶權(quán)限表、用戶表、角色表、用戶角色表
1、基于JavaSe的Shiro的基本使用
1、導(dǎo)入shiro依賴
<dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.5.1</version> </dependency>
但是出現(xiàn)了一點(diǎn)問題:就是引入這個(gè)依賴后pom文件就會(huì)報(bào)錯(cuò),可以在pom文件中加入加入阿里云的代理倉(cāng)庫(kù):
<repositories><!-- 阿里云代碼庫(kù) --> <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("請(qǐng)輸入用戶名:"); String username = sc.nextLine(); System.out.println("請(qǐng)輸入密碼:"); String password = sc.nextLine(); //創(chuàng)建安全管理器 DefaultSecurityManager securityManager = new DefaultSecurityManager(); //創(chuàng)建realm IniRealm realm = new IniRealm("classpath:shiro.ini"); //將realm設(shè)置給安全管理器 securityManager.setRealm(realm); //將realm設(shè)置給SecurityUtils工具 SecurityUtils.setSecurityManager(securityManager); //通過SecurityUtils獲取subject對(duì)象 Subject subject = SecurityUtils.getSubject(); //認(rèn)證流程 UsernamePasswordToken token = new UsernamePasswordToken(username, password); System.out.println(subject.isAuthenticated());//false //完成認(rèn)證 subject.login(token); System.out.println(subject.isAuthenticated());//true //授權(quán) //判斷是否有某個(gè)角色 subject.hasRole("seller");//true //判斷是否有某個(gè)權(quán)限 boolean permitted = subject.isPermitted("oredr-del"); System.out.println(permitted);//true } }
4、shiro認(rèn)證授權(quán)流程
(1) 通過subject.login(token)進(jìn)行登錄,就會(huì)將token包含的用戶信息(賬號(hào)和密碼)傳遞給SecurityManager
(2) SecurityManager會(huì)調(diào)用Authentication進(jìn)行認(rèn)證
(3) Authentication就會(huì)根據(jù)Realm安全信息進(jìn)行認(rèn)證校驗(yàn)
(4) Realm根據(jù)得到的token,調(diào)用doGetAuthenticationInfo()方法進(jìn)行認(rèn)證
(5) 認(rèn)證完成后一層層返回到subject
2、SpringBoot整合shiro
- 1、導(dǎo)入shiro依賴:
- 2、配置shiro過濾器:攔截進(jìn)行認(rèn)證和授權(quán)的用戶
- 3、配置SecurityManager到Spring容器
- 4、配置Realm(SecurityManager需要Realm)
1. 導(dǎo)入依賴
<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要完成認(rèn)證和校驗(yàn)需要Realm DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(iniRealm); return securityManager; } //配置shiro的過濾器 @Bean public ShiroFilterFactoryBean shiroFilter(DefaultSecurityManager securityManager) { //過濾器工廠 ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean(); //過濾器是進(jìn)行權(quán)限校驗(yàn)的核心,進(jìn)行認(rèn)證和授權(quán)需要SecurityManager filter.setSecurityManager(securityManager); //設(shè)置攔截規(guī)則 //anon:匿名用戶可以訪問,authc:授權(quán)用戶可以訪問 Map<String, String> filterMap = new HashMap<>(); filterMap.put("/","anon"); //項(xiàng)目個(gè)根路徑不攔截 filterMap.put("/login.html","anon"); //登錄頁(yè)面不攔截 filterMap.put("/register.html","anon"); //注冊(cè)頁(yè)面不攔截 filterMap.put("/user/login","anon"); //登錄不攔截 filterMap.put("/user/regist","anon"); //注冊(cè)不攔截 filterMap.put("/static/**","anon"); //靜態(tài)頁(yè)面不攔截 filterMap.put("/**","authc"); //除了上面的請(qǐng)求路徑,其他路徑都要攔截 filter.setFilterChainDefinitionMap(filterMap); //設(shè)置默認(rèn)的登錄頁(yè)面 filter.setLoginUrl("/login.html"); //設(shè)置未授權(quán)訪問的頁(yè)面路徑(一個(gè)頁(yè)面如果未授權(quán)讓其跳轉(zhuǎn)到登錄頁(yè)面) filter.setUnauthorizedUrl("/login.html"); return filter; } }
3. 進(jìn)行認(rèn)證測(cè)試
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登錄頁(yè)面:
<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、認(rèn)證成功:跳到index首頁(yè)
6、認(rèn)證失敗,跳到登錄頁(yè)面
3、JdbcRealm實(shí)現(xiàn)權(quán)限管理
1. JdbcRealm表結(jié)構(gòu)
這些表名和表結(jié)構(gòu)都是固定的不能更改:
用戶信息表: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"); -- 庫(kù)管人員 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"); -- 行政人員
權(quán)限信息表:roles_permissions
create table roles_permissions( id int primary key auto_increment, role_name varchar(60) not null, permission varchar(100) not null ) -- 管理員具備所有權(quán)限 insert into roles_permissions(role_name,permission) values("admin","*"); -- 庫(kù)管人員 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ù)庫(kù)配置 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 # 連接池配置 #連接池建立時(shí)創(chuàng)建的初始化連接數(shù) spring.datasource.druid.initial-size=5 #連接池中最大的活躍連接數(shù) spring.datasource.druid.max-active=20 #連接池中最小的活躍連接數(shù) spring.datasource.druid.min-idle=5 # 配置獲取連接等待超時(shí)的時(shí)間 spring.datasource.druid.max-wait=60000 # mybatis 配置 mybatis.mapper-locations=classpath:mappers/*Mapper.xml mybatis.type-aliases-package=com.hh.beans
2、導(dǎo)入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會(huì)自行從數(shù)據(jù)庫(kù)中查詢用戶和權(quán)限數(shù)據(jù)(前提是數(shù)據(jù)庫(kù)表結(jié)構(gòu)要符合JdbcRealm表結(jié)構(gòu)) jdbcRealm.setDataSource(dataSource); //jdbcRealm默認(rèn)開啟認(rèn)證功能,如果想要開啟授權(quán)功能,需要手動(dòng)開啟 jdbcRealm.setPermissionsLookupEnabled(true); return jdbcRealm; } //將DefaultSecurityManager交給Spring容器來創(chuàng)建和管理 @Bean public DefaultSecurityManager getDefaultSecurityManager(JdbcRealm jdbcRealm) { //SecurityManager要完成認(rèn)證和校驗(yàn)需要Realm DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager(); securityManager.setRealm(jdbcRealm); return securityManager; } //配置shiro的過濾器 @Bean public ShiroFilterFactoryBean shiroFilter(DefaultSecurityManager securityManager) { //過濾器工廠 ShiroFilterFactoryBean filter = new ShiroFilterFactoryBean(); //過濾器是進(jìn)行權(quán)限校驗(yàn)的核心,進(jìn)行認(rèn)證和授權(quán)需要SecurityManager filter.setSecurityManager(securityManager); //設(shè)置攔截規(guī)則 //anon:匿名用戶可以訪問,authc:授權(quán)用戶可以訪問 Map<String, String> filterMap = new HashMap<>(); filterMap.put("/", "anon"); //項(xiàng)目個(gè)根路徑不攔截 filterMap.put("/login.html", "anon"); //登錄頁(yè)面不攔截 filterMap.put("/register.html", "anon"); //注冊(cè)頁(yè)面不攔截 filterMap.put("/user/login", "anon"); //登錄不攔截 filterMap.put("/user/regist", "anon"); //注冊(cè)不攔截 filterMap.put("/static/**", "anon"); //靜態(tài)頁(yè)面不攔截 filterMap.put("/**", "authc"); //除了上面的請(qǐng)求路徑,其他路徑都要攔截 filter.setFilterChainDefinitionMap(filterMap); //設(shè)置默認(rèn)的登錄頁(yè)面 filter.setLoginUrl("/login.html"); //設(shè)置未授權(quán)訪問的頁(yè)面路徑(一個(gè)頁(yè)面如果未授權(quán)讓其跳轉(zhuǎn)到登錄頁(yè)面) filter.setUnauthorizedUrl("/login.html"); return filter; } }
4、進(jìn)行認(rèn)證測(cè)試:和上面測(cè)試方法相同
由于只要我們按照規(guī)定寫了數(shù)據(jù)庫(kù)表結(jié)構(gòu),那么既可以直接使用數(shù)據(jù)庫(kù)中的信息
4、實(shí)現(xiàn)前端的權(quán)限菜單展示
1. 在Thymeleaf中使用標(biāo)簽
1、在pom.xml文件中導(dǎo)入thymeleaf模版對(duì)shiro標(biāo)簽支持的依賴
<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. 常用標(biāo)簽
2.1 guest
判斷用戶是否是游客身份,如果是游客身份則顯示此標(biāo)簽內(nèi)容
<shiro:guest> 歡迎游客,<a href="login.html" rel="external nofollow" rel="external nofollow" >請(qǐng)登錄</a> </shiro:guest>
2.2 user
判斷用戶是否是認(rèn)證身份,如果是認(rèn)證身份則顯示此標(biāo)簽內(nèi)容
<shiro:user> 已登錄用戶 </shiro:user>
2.3 principal
獲取當(dāng)前登錄用戶名
<shiro:user> 已登錄用戶<shiro:principal/>歡迎您! </shiro:user>
2.4 hasRole
當(dāng)期那登錄用戶的角色
<shiro:user> 當(dāng)前用戶<shiro:principal/>歡迎您! 當(dāng)前用戶為<shiro:hasRole name="admin">超級(jí)管理員</shiro:hasRole> <shiro:hasRole name="cmanager">倉(cāng)管人員</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
當(dāng)前登錄用戶具有的權(quán)限
<!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" >請(qǐng)登錄</a> </shiro:guest> <shiro:user> 當(dāng)前用戶<shiro:principal/>歡迎您! 當(dāng)前用戶為<shiro:hasRole name="admin">超級(jí)管理員</shiro:hasRole> <shiro:hasRole name="cmanager">倉(cāng)管人員</shiro:hasRole> <shiro:hasRole name="xmanager">銷售人員</shiro:hasRole> <shiro:hasRole name="kmanager">客服人員</shiro:hasRole> <shiro:hasRole name="zmanager">行政人員</shiro:hasRole> </shiro:user> 倉(cāng)庫(kù)管理: <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" >入庫(kù)</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" >出庫(kù)</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. 認(rèn)證流程回顧
5、自定義Realm實(shí)現(xiàn)權(quán)限管理
1. 表結(jié)構(gòu)的設(shè)計(jì)
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 權(quán)限表: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","入庫(kù)"); insert into tb_permissions(permission_code,permission_name) values("sys:c:delete","出庫(kù)"); 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具有所有角色,代表具有所有權(quán)限,不用給他分配權(quán)限 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 角色權(quán)限表:tb_rps
create table tb_rps( rid int not null, pid int not null ); -- 給角色2(倉(cāng)管)分配權(quán)限 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(銷售)分配權(quán)限 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(客服)分配權(quán)限 insert into tb_rps(rid,pid) values(4,11); insert into tb_rps(rid,pid) values(4,12); -- 給角色5(行政)分配權(quán)限 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層實(shí)現(xiàn)
shiro 進(jìn)行認(rèn)證需要用戶信息:
- 根據(jù)用戶名查詢用戶信息
shiro進(jìn)行權(quán)限管理需要當(dāng)前用戶的角色和權(quán)限:
- 根據(jù)用戶名查詢當(dāng)前用戶的角色列表
- 根據(jù)用戶名查詢當(dāng)前用戶的權(quán)限列表
2.1 根據(jù)用戶名查詢用戶信息
實(shí)體類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ù)用戶名查詢權(quán)限列表
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 導(dǎo)入依賴
<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相當(dāng)于數(shù)據(jù)源,從數(shù)據(jù)庫(kù)中查詢出認(rèn)證信息和授權(quán)信息 @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就行權(quán)限校驗(yàn)的核心,進(jìn)行認(rèn)證和授權(quán)是需要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"); //設(shè)置未授權(quán)訪問的頁(yè)面路徑() filter.setUnauthorizedUrl("/login.html"); return filter; } }
3.3 自定義Realm
/** * 自定義Realm的規(guī)范: * 1、創(chuàng)建一個(gè)類實(shí)現(xiàn)AuthorizingRealm,重寫里面的兩個(gè)方法 * 2、重寫getName()方法,返回當(dāng)前Realm的自定義名稱 */ public class MyRealm extends AuthorizingRealm { @Autowired private UserDao userDao; @Autowired private RoleDao roleDao; @Autowired private PermissionDao permissionDao; public String getName(){ return "myRealm"; } /** * 獲取認(rèn)證信息:將用戶密碼查詢出來交給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ù)庫(kù)中查詢用戶信息 User user = userDao.queryUserByUsername(username); if(user==null){ return null; } //將查詢出來的密碼封裝成安全信息給shiro AuthenticationInfo info = new SimpleAuthenticationInfo( username,//當(dāng)前用戶的用戶名 user.getUserPwd(),//從數(shù)據(jù)庫(kù)中查詢出來的安全數(shù)據(jù) getName() ); return info; } /** * 獲取授權(quán)信息:將當(dāng)前用戶的角色和權(quán)限查詢出交給shiro * @param principalCollection */ @SneakyThrows @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { //獲取用戶的用戶名 String username = (String)principalCollection.iterator().next(); //根據(jù)用戶名查詢用戶的角色列表 Set<String> roleNames = roleDao.queryRoleNamesByUsername(username); //根據(jù)用戶名查詢用戶的權(quán)限列表 Set<String> ps = permissionDao.queryPermissionsByUsername(username); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(); info.setRoles(roleNames); info.setStringPermissions(ps); return info; } }
測(cè)試結(jié)果:
以上為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
Map集合中獲取key-value值的實(shí)現(xiàn)方法
這篇文章主要介紹了Map集合中獲取key-value值的實(shí)現(xiàn)方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03Mybatis實(shí)戰(zhàn)之TypeHandler高級(jí)進(jìn)階
本文主要介紹了自定義的枚舉TypeHandler的相關(guān)知識(shí),具有很好的參考價(jià)值,下面跟著小編一起來看下吧2017-02-02Java的ConcurrentHashMap中不能存儲(chǔ)null的原因解析
眾所周知,在Java中Map可以存儲(chǔ)null,而ConcurrentHashMap不能存儲(chǔ)null值,那么為什么呢?今天通過源碼分析給大家詳細(xì)解讀,感興趣的朋友一起看看吧2022-07-07spring中實(shí)現(xiàn)容器加載完成后再執(zhí)行自己的方法
這篇文章主要介紹了spring中實(shí)現(xiàn)容器加載完成后再執(zhí)行自己的方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02mybatis-plus實(shí)現(xiàn)自定義SQL、多表查詢與多表分頁(yè)查詢語句實(shí)例
mybatisplus是個(gè)很好用的插件,相信小伙伴們都知道,下面這篇文章主要給大家介紹了關(guān)于mybatis-plus實(shí)現(xiàn)自定義SQL、多表查詢與多表分頁(yè)查詢語句的相關(guān)資料,需要的朋友可以參考下2022-09-09