发表于: 2019-11-07 21:41:11
1 813
一、今天完成的事
1.学习shiro
1.shiro介绍
Shiro是一个Java安全框架,执行身份验证、授权、密码、会话管理。Shiro是Apache 的一个开源项目,前身是JSecurity 项目,始于2003年初。
Shiro 可以为任何应用提供安全保障 - 从命令行应用、移动应用到大型网络及企业应用。
shiro 解决了应用安全的四要素:
认证 - 用户身份识别,常被称为用户“登录”;
授权 - 访问控制;
密码加密 - 保护或隐藏数据防止被偷窥;
会话管理 - 每用户相关的时间敏感的状态。
同时,Shiro另外支持了一些辅助特性:如 Web 应用安全、单元测试和多线程,它们的存在强化了上面提到的四个要素。
2.shiro的优势
1、易于使用 - 易用性是这个项目的最终目标。应用安全有可能会非常让人糊涂,令人沮丧,并被认为是“必要之恶”【译注:比喻应用安全方面的编程。】。若是能让它简化到新手都能很快上手,那它将不再是一种痛苦了。
2、广泛性 - 没有其他安全框架可以达到 Apache Shiro 宣称的广度,它可以为你的安全需求提供“一站式”服务。
3、灵活性 - Apache Shiro 可以工作在任何应用环境中。虽然它工作在 Web、EJB 和 IoC 环境中,但它并不依赖这些环境。Shiro 既不强加任何规范,也无需过多依赖。
4、Web 能力 - Apache Shiro 对 Web 应用的支持很神奇,允许你基于应用 URL 和 Web 协议(如 REST)创建灵活的安全策略,同时还提供了一套控制页面输出的 JSP 标签库。
5、可插拔 - Shiro 干净的 API 和设计模式使它可以方便地与许多的其他框架和应用进行集成。你将看到 Shiro 可以与诸如 Spring、Grails、Wicket、Tapestry、Mule、Apache Camel、Vaadin 这类第三方框架无缝集成。
6、支持 - Apache Shiro 是 Apache 软件基金会成员,这是一个公认为了社区利益最大化而行动的组织。项目开发和用户组都有随时愿意提供帮助的友善成员。
3.核心概念
Shiro的核心概念有三个:Subject,SecurityManager 和 Realms。
1.subject
subject 被Shiro 描述为一个主体,对于web应用来说,可以简单理解为用户。
Subject currentUser = SecurityUtils.getSubject();
获得Subject 后,通过这个对象,我们可以对其进行绝大多数安全操作:登录、登出、访问会话、执行授权检查等。
2.SecurityManager
Subject 的幕后推手是 SecurityManager,Subject 代表了当前用户的安全操作,SecurityManager则管理所有用户的安全操作。
SecurityManager 是 Shiro 框架的核心,充当“保护伞”,引用了多个内部嵌套安全组件,它们形成了对象图。但是,一旦 SecurityManager 及其内部对象图配置好,它就会退居幕后,应用开发人员几乎把他们的所有时间都花在 Subject API 调用上。
一个应用只需要一个 SecurityManager,是一个单例对象。它的缺省实现是POJO,Shiro 里的其他组件也是一样。因此,可以用POJO兼容的任何配置机制进行配置:普通的Java代码、Spring xml、YAML、和 ini 文件等。基本上,能够实例化类和调用JavaBean兼容方法的任何配置形式都可以。
3.Realm
Realm 充当了 Shiro 与应用安全数据间的“桥梁”或者“连接器”。当切实与像用户帐户这类安全相关数据进行交互,执行认证(登录)和授权(访问控制)时,Shiro 会从应用配置的 Realm 中查找很多内容。
从某种意义上讲,Realm 实际上就是一个安全相关的 DAO:它封装了数据源的连接细节,并在需要时将相关数据提供给 Shiro。
注意:在配置Shiro 时,必须指定至少一个 Realm ,可以配置多个。
Shiro 内置了一些Realm ,支持多种数据源的连接,如JDBC、LDAP、INI文件的连接等。另外,可以自定义Realm 实现,方便个性化的应用场景。
4.如何使用shiro
在配置文件中定义需要给权限的目标
在程序中调用subject进行验证。
5.在springboot中用shiro
导入依赖
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.3.2</version>
</dependency>
springboot中集成shiro相对简单,只需要两个类:
shiroConfig
就是对shiro的一些配置。
package com.ksy.config;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Bean;
import java.util.LinkedHashMap;
import java.util.Map;
/**
* @author shiyang
* @PackageName com.ksy.config
* @ClassName demo
* @Description
* @create 2019-11-07 20:09
*/
public class ShiroConfig {
/**
* 一个过滤器,拦截url
* @param securityManager
* @return
*/
@Bean(name = "shiroFilter")
public ShiroFilterFactoryBean shiroFilter(SecurityManager securityManager) {
ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
//必须set项
shiroFilterFactoryBean.setSecurityManager(securityManager);
//设置登录页面
shiroFilterFactoryBean.setLoginUrl("/login");
//设置登录成功跳转页面
shiroFilterFactoryBean.setSuccessUrl("/home");
//权限不足跳转的页面
shiroFilterFactoryBean.setUnauthorizedUrl("/register");
//拦截器,下面的属性就是配置不会被拦截的url
Map<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
// authc:所有url都必须认证通过才可以访问; anon:所有url都都可以匿名访问,封装在DefaultWebSecurityManager中
filterChainDefinitionMap.put("/home","anon");
//这行代码必须放在所有权限设置的最后,不然会导致所有 url 都被拦截 剩余的都需要认证
filterChainDefinitionMap.put("/**", "authc");
shiroFilterFactoryBean.setFilterChainDefinitionMap(filterChainDefinitionMap);
return shiroFilterFactoryBean;
}
@Bean
public SecurityManager securityManager() {
DefaultWebSecurityManager defaultWebSecurityManager = new
DefaultWebSecurityManager();
defaultWebSecurityManager.setRealm(customRealm());
return defaultWebSecurityManager;
}
@Bean
public CustomRealm customRealm() {
CustomRealm customRealm = new CustomRealm();
return customRealm;
}
}
shiroFilter方法: 这个方法看名字就知道了:shiro的过滤器,可以设置登录页面(setLoginUrl)、权限不足跳转页面(setUnauthorizedUrl)、具体某些页面的权限控制或者身份认证。 注意:这里是需要设置SecurityManager(setSecurityManager)。 默认的过滤器还有:anno、authc、authcBasic、logout、noSessionCreation、perms、port、rest、roles、ssl、user过滤器。 具体的大家可以查看package org.apache.shiro.web.filter.mgt.DefaultFilter。这个类,常用的也就authc、anno。 securityManager 方法: 查看源码可以知道 securityManager是一个接口类,我们可以看下它的实现类:
由于项目是一个web项目,所以我们使用的是DefaultWebSecurityManager ,然后设置自己的Realm。
CustonRealme类
自定义的CustonRealme继承AuthorizingRealm。并且重写父类中的doGetAuthorizationInfo(权限相关)、doGetAuthenticationInfo(身份验证)这两个方法。
package com.ksy.config;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import java.util.HashSet;
import java.util.Set;
/**
* @author shiyang
* @PackageName com.ksy.config
* @ClassName demo
* @Description
* @create 2019-11-07 20:44
*/
public class CustomRealm extends AuthorizingRealm {
/**
* 权限认证,即登录过后,每个身份不一定,对应的所能看的页面也不一样。
* @param principalCollection
* @return
*/
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
String uesrname = (String) SecurityUtils.getSubject().getPrincipal();
SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
Set<String> stringSet = new HashSet<>();
stringSet.add("user:");
stringSet.add("user");
info.setStringPermissions(stringSet);
return info;
}
/**
* 身份认证。即登录通过账号和密码验证登陆人的身份信息。
* @param authenticationToken
* @return
* @throws AuthenticationException
*/
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {System.out.println("-------身份认证方法--------");
//getPrincipal()返回验证后用户名
String userName = (String) authenticationToken.getPrincipal();
//返回验证后的密码
String userPwd = new String((char[]) authenticationToken.getCredentials());
//根据用户名从数据库获取密码
List<> userList = sysUserService.selectByMap(map);
if(userList.size()!=0){
user = userList.get(0);
}
String password = "123";
if (userName == null) {
throw new AccountException("用户名不正确");
} else if (!userPwd.equals(password )) {
throw new AccountException("密码不正确");
}
return new SimpleAuthenticationInfo(userName, password,getName());
}
}
说明: 自定义的Realm类继承AuthorizingRealm类,并且重载doGetAuthorizationInfo和doGetAuthenticationInfo两个方法。 doGetAuthorizationInfo: 权限认证,即登录过后,每个身份不一定,对应的所能看的页面也不一样。 doGetAuthenticationInfo:身份认证。即登录通过账号和密码验证登陆人的身份信息。
二、遇到的问题
关于shiro自定义验证还没有写完,学习的demo是死数据,想通过数据库获取用户名密码来拉验证,在springboot中user类还没写完,明天在看一看怎么实现,其他的看了源码大概理解shiro是怎么实现的。
三、收获
四、明天的计划
解决上述问题
评论