关于shiro:权限管理

73次阅读

共计 6785 个字符,预计需要花费 17 分钟才能阅读完成。

一、权限框架介绍

1. 权限治理

实质:用户身份认证 + 受权

流程:用户首先通过身份认证,通过后即可拜访该资源
1.1 用户身份认证
  
1.2 受权流程

2. 权限框架

Shiro 和 Spring Security 比拟
(1)Shiro 比 Spring 更容易应用,实现和了解
(2)Spring Security 有更好的社区反对
(3)Apache Shiro 在 Spring Security 解决密码学方面有一个额定的模块
(4)Spring-security 对 spring 联合较好,如果我的项目用的 springmvc,应用起来很不便。然而如果我的项目中没有用到 spring,那就不要思考它了。
(5)Shiro 功能强大、且 简略、灵便。是 Apache 下的我的项目比拟牢靠,且不跟任何的框架或者容器绑定,能够独立运行

二、Shiro 根底介绍

1. Shiro 三个外围组件

1.1 Subject(以后操作用户)
   不仅仅指人,也能够是第三方过程、后盾帐户(Daemon Account)或其余相似事物。Subject 代表了以后用户的平安操作,SecurityManager 则治理所有用户的平安操作。

1.2 SecurityManager(保护核心)
   Shiro 框架的外围,典型的 Facade 模式,用来协调外部组件实例,并提供平安治理的各种服务。

1.3 Realm(数据中心)
  对用户认证(登录)和受权(访问控制)时,Shiro 会从配置的 Realm 中查找用户及其权限信息。
   当配置 Shiro 时,至多指定一个 Realm,用于认证和(或)受权。配置多个 Realm 是能够的,然而至多须要一个。
   Shiro 内置了能够连贯大量平安数据源(又名目录)的 Realm,如 LDAP、关系数据库(JDBC)、相似 INI 的文本配置资源以及属性文件等。如果缺省的 Realm 不能满足需要,你还能够插入代表自定义数据源的本人的 Realm 实现。

2. Shiro 相干类介绍

(1)Authentication 认证 —- 用户登录
(2)Authorization 受权 — 用户具备哪些权限
(3)Cryptography 平安数据加密
(4)Session Management 会话治理
(5)Web Integration web 系统集成
(6)Interations 集成其它利用,spring、缓存框架

3. Shiro 特点

(1)易于了解的 Java Security API;
(2)简略的身份认证(登录),反对多种数据源(LDAP,JDBC,Kerberos,ActiveDirectory 等);
(3)对角色的简略的签权(访问控制),反对细粒度的签权;
(4)反对一级缓存,以晋升应用程序的性能;
(5)内置的基于 POJO 企业会话治理,实用于 Web 以及非 Web 的环境;
(6)异构客户端会话拜访;
(7)非常简单的加密 API;
(8)不跟任何的框架或者容器捆绑,能够独立运行

三、Spring Boot 整合 Shiro 代码实战

3.1 pom.xml 中增加依赖

<dependency>
 <groupId>com.h2database</groupId>
 <artifactId>h2</artifactId>
 <scope>runtime</scope>
</dependency>
<dependency>
 <groupId>org.apache.shiro</groupId>
 <artifactId>shiro-spring</artifactId>
 <version>1.3.2</version>
</dependency>

3.2 编写测试 Controller 类

@RequiresPermissions("user:list")
@RequiresRoles("admin")
@ResponseBody
@RequestMapping("/hello")
public String  hello(){System.out.println(person);
 return "hello world";
}
@RequestMapping(value = "/login", method = RequestMethod.GET)
@ResponseBody
public String defaultLogin() {return "首页";}
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public String login(@RequestParam("username") String username, @RequestParam("password") String password) {// 从 SecurityUtils 里边创立一个 subject Subject subject = SecurityUtils.getSubject();
 // 在认证提交前筹备 token(令牌)UsernamePasswordToken token = new UsernamePasswordToken(username, password);
 // 执行认证登陆
 try {subject.login(token);
 } catch (UnknownAccountException uae) {return "未知账户";} catch (IncorrectCredentialsException ice) {return "明码不正确";} catch (LockedAccountException lae) {return "账户已锁定";} catch (ExcessiveAttemptsException eae) {return "用户名或明码谬误次数过多";} catch (AuthenticationException ae) {return "用户名或明码不正确!";}
 if (subject.isAuthenticated()) {return "登录胜利";} else {token.clear();
 return "登录失败";
 }
}

3.3 配置类

@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
 shiroFilterFactoryBean.setSecurityManager(securityManager);   shiroFilterFactoryBean.setSecurityManager(securityManager);
        
        // 增加 Shiro 内置过滤器
        /**
         * Shiro 内置过滤器,能够实现权限相干的拦截器
         *    罕用的过滤器:*       anon: 无需认证(登录)能够拜访
         *       authc: 必须认证才能够拜访
         *       user: 如果应用 rememberMe 的性能能够间接拜访
         *       perms:该资源必须失去资源权限才能够拜访
         *       role: 该资源必须失去角色权限才能够拜访
         */

 shiroFilterFactoryBean.setLoginUrl("/login");// 登录页
 shiroFilterFactoryBean.setUnauthorizedUrl("/notRole");
 Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
 // <!-- authc: 所有 url 都必须认证通过才能够拜访; anon: 所有 url 都都能够匿名拜访 -->
 filterChainDefinitionMap.put("/webjars/**", "anon");
 filterChainDefinitionMap.put("/login", "anon");
 filterChainDefinitionMap.put("/", "anon");
 filterChainDefinitionMap.put("/front/**", "anon");
 filterChainDefinitionMap.put("/api/**", "anon");
 filterChainDefinitionMap.put("/admin/**", "authc");
 filterChainDefinitionMap.put("/user/**", "authc");
 filterChainDefinitionMap.put("/hello/**","perms[user:add]");
 // 次要这行代码必须放在所有权限设置的最初,不然会导致所有 url 都被拦挡 残余的都须要认证
 filterChainDefinitionMap.put("/**", "authc");
 shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
 return shiroFilterFactoryBean;
}
@Bean
public DefaultWebSecurityManager securityManager() {DefaultWebSecurityManager defaultSecurityManager = new DefaultWebSecurityManager();
 defaultSecurityManager.setRealm(customRealm());
 DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
 DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
 defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
 subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
 defaultSecurityManager.setSubjectDAO(subjectDAO);
 return defaultSecurityManager;
}
@Bean
@DependsOn("lifecycleBeanPostProcessor")
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
 defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
 return defaultAdvisorAutoProxyCreator;
}
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {return new LifecycleBeanPostProcessor();
}
@Bean
public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor() {AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor = new AuthorizationAttributeSourceAdvisor();
 authorizationAttributeSourceAdvisor.setSecurityManager(securityManager());
 return authorizationAttributeSourceAdvisor;
}
@Bean
public CustomRealm customRealm() {CustomRealm customRealm = new CustomRealm();
 return customRealm;
}

3.4 Realm

/**
 * 权限认证,即登录过后,每个身份不肯定,对应的所能看的页面也不一样。* @param principalCollection
 * @return
 */
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
 User user = null;
 String username = "";
 if (Objects.nonNull(principalCollection)){user = (User)principalCollection.getPrimaryPrincipal();}
 username = (String) SecurityUtils.getSubject().getPrincipal();
 SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
 // 用户角色
 Set<String> roleSets = new HashSet<>();
 roleSets.add("admin");
 roleSets.add("test");
 info.setRoles(roleSets);
 // 角色对应的权限
 Set<String> permissionSet = new HashSet<>();
 permissionSet.add("user:show");
 permissionSet.add("user:admin");
 info.addStringPermissions(permissionSet);
 return info;
}
/**
 * 身份认证。即登录通过账号和明码验证登陆人的身份信息。* @param authenticationToken
 * @return
 * @throws AuthenticationException
 */@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {System.out.println("------- 身份认证办法 --------");
 //authenticationToken.getCredentials()----token? 如何来?String token = (String) authenticationToken.getCredentials();
 if (StringUtils.isEmpty(token)){HttpServletRequest request = ((ServletRequestAttributes) (RequestContextHolder.currentRequestAttributes())).getRequest();
 Map<String, String[]> parameterMap = request.getParameterMap();
 Set<Map.Entry<String, String[]>> entrys = parameterMap.entrySet();
 for (Map.Entry<String, String[]> entry:entrys) {System.out.println(entry.getKey()+"============"+entry.getValue());
 }
 throw new AuthenticationException("token 为空");
 }
 User user = this.checkAuthenticationToken(token);
 //String userName = (String) authenticationToken.getPrincipal();
 //String userPwd = new String((char[]) authenticationToken.getCredentials()); return new SimpleAuthenticationInfo(user, token,getName());
}

正文完
 0