分布式shiro权限验证
本文介绍项目中如何应用shiro做分布权限。
因为shiro是基于单服务的,session共享后,可做多服务。分布式权限,需要使用相同的域名(session的作用域)。
基本思路,通过统一的登录服务进行登录,通过iframe框架进行菜单功能跳转。
构建首页页面结构
header.html
<!DOCTYPE html>
<html lang="en">
<body>
<div th:fragment="header">
<div>header</div>
</div>
</body>
</html>
Navigator.html 菜单可通过后台获取数据构建,路径位网关域名的绝对路径,target到iframe,此处域名以localhost为例。
<!DOCTYPE html>
<html lang="en">
<body>
<div th:fragment="navigator">
<div>navigator</div>
<div>
<li><a href="http://localhost:9000/paw-authorize-shiro-api/home" target="mainFrame">a link</a></li>
<li><a href="http://localhost:9000/paw-sky-api/index" target="bodyFrame">sky</a></li>
</div>
</div>
</body>
</html>
最终index.html 可通过现有的一些前端框架构建 上header,左菜单栏,右工作栏的美观布局。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Shiro Session</title>
</head>
<body>
<script>
// window.location.href='http://172.20.25.8:9000/paw-authorize-shiro-api/home';
</script>
<div style="width: 100%;height: 100px">
<div th:include="../templates/header"></div>
</div>
<div style="display: flex">
<div style="width: 200px;height: 100%">
<div th:include="../templates/navigator"></div>
</div>
<div style="width: 1500px;height: 1000px">
frameLabelStart--frameLabelEnd
</div>
</div>
</body>
</html>
login之后跳转到index.html,之后整个页面框架不变,通过菜单调用相应的微服务,工作区mainFrame内容转换。
菜单<li><a href="http://localhost:9000/paw-sky-api/index" target="bodyFrame">sky</a></li>
的服务
配置shiroConfig,登录地址指向登录服务,除登录服务外不需要配置登录页面及index页面,login也交由登录服务处理
shiro:
loginUrl: http://localhost:8081/login
successUrl: http://localhost:8081/index
配置类,进行session获取及注解权限处理
@Configuration
public class ShiroConfig {
public ShiroConfig() {
}
@Bean
public UserRealm userRealm() {
UserRealm userRealm = new UserRealm();
userRealm.setCredentialsMatcher(this.credentialsMatcher());
return userRealm;
}
@Bean
public ShiroFilterChainDefinition shiroFilterChainDefinition() {
DefaultShiroFilterChainDefinition chainDefinition = new DefaultShiroFilterChainDefinition();
chainDefinition.addPathDefinition("/captcha", "anon");
chainDefinition.addPathDefinition("/logout", "anon");
chainDefinition.addPathDefinition("/layuiadmin/**", "anon");
chainDefinition.addPathDefinition("/druid/**", "anon");
chainDefinition.addPathDefinition("/api/**", "anon");
chainDefinition.addPathDefinition("/login", "anon");
chainDefinition.addPathDefinition("/**", "authc");
return chainDefinition;
}
@Bean
public HashedCredentialsMatcher credentialsMatcher() {
HashedCredentialsMatcher credentialsMatcher = new HashedCredentialsMatcher();
credentialsMatcher.setHashAlgorithmName("SHA-256");
credentialsMatcher.setStoredCredentialsHexEncoded(false);
credentialsMatcher.setHashIterations(1024);
return credentialsMatcher;
}
@Bean
public SessionsSecurityManager securityManager() {
DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
// securityManager.setRealm(this.userRealm());
return securityManager;
}
至此整个分布式页面权限完成。
gitee: https://gitee.com/tg_seahorse/paw-demos/tree/master
或分支 https://gitee.com/tg_seahorse/paw-demos/tree/paw-authorize/
思考:如何将shiro相关内容提取到一个公共服务,其他页面服务只需要引入此公共服务即可实现shiro权限验证。