7.Shiro安全框架

1.Shiro简介

1.1 什么是Shiro?

Apache Shiro 是一个Java 的安全(权限)框架。
Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境,也可以用在JavaEE环境。
Shiro可以完成,认证,授权,加密,会话管理,Web集成,缓存等。
session,即便不使用web容器,它也可以使用session
下载地址:http://shiro.apache.org

1.2 有哪些功能?

在这里插入图片描述

  1. Authentication身份认证、登录,验证用户是不是拥有相应的身份;
  2. Authorization授权,即权限验证,验证某个已认证的用户是否拥有某个权限,即判断用户能否进行什么操作,如:验证某个用户是否拥有某个角色,或者细粒度的验证某个用户对某个资源是否具有某个权限!
  3. Session Manager会话管理,即用户登录后就是第一次会话,在没有退出之前,它的所有信息都在会话中;会话可以是普通的JavaSE环境,也可以是Web环境;
  4. Cryptography加密,保护数据的安全性,如密码加密存储到数据库中,而不是明文存储;
  5. Web Support:Web支持,可以非常容易的集成到Web环境
  6. Caching缓存,比如用户登录后,其用户信息,拥有的角色、权限不必每次去查,这样可以提高效率
  7. Concurrency:Shiro支持多线程应用的并发验证,即,如在一个线程中开启另一个线程,能把权限自动的传播过去
  8. Testing提供测试支持
  9. Run As:允许一个⽤户假装为另一个用户(如果他们允许)的身份进行访问;
  10. Remember Me记住我,这个是非常常见的功能,即一次登录后,下次再来的话不用登录了

1.3 Shiro架构(外部)

从外部来看Shiro,即从应用程序角度来观察如何使用shiro完成工作:
在这里插入图片描述

  1. Subject:应用代码直接交互的对象是Subject,也就是说Shiro的对外API核心就是Subject,
    Subject代表了当前的用户,这个用户不一定是一个具体的人。与当前应用交互的任何东西都是
    Subject,如网络爬虫,机器人等,与Subject的所有交互都会委托给SecurityManager;Subject
    其实是一个门面,SecurityManageer 才是实际的执行者
  2. SecurityManager安全管理器,即所有与安全有关的操作都会与SercurityManager交互,并且它管理着所有的Subject,可以看出它是Shiro的核心,它负责与Shiro的其他组件进行交互,它相当于SpringMVC的DispatcherServlet的角色
  3. Realm:Shiro从Realm获取安全数据(如用户,角色,权限),就是说SecurityManager 要验证
    用户身份,那么它需要从Realm 获取相应的用户进行比较,来确定用户的身份是否合法;也需要从Realm得到用户相应的角色、权限,进行验证用户的操作是否能够进行,可以把Realm看成DataSource;

1.4 Shiro架构(内部)

在这里插入图片描述

  1. Subject :任何可以与应用交互的 ‘用户’;
  2. Security Manager:相当于SpringMVC中的DispatcherServlet;是Shiro的心脏,所有具体的交互都通过Security Manager进行控制,它管理着所有的Subject,且负责进行认证,授权,会话,及缓存的管理。
  3. Authenticator:负责Subject认证,是一个扩展点,可以自定义实现;可以使用认证策略
    (Authentication Strategy),即什么情况下算用户认证通过了;
  4. Authorizer:授权器,即访问控制器,用来决定主体是否有权限进行相应的操作;即控制着用户能访问应用中的哪些功能;
  5. Realm:可以有一个或者多个的realm,可以认为是安全实体数据源,即用于获取安全实体的,可以用JDBC实现,也可以是内存实现等,由用户提供;所以一般在应用中都需要实现自己的realm
  6. SessionManager:管理Session生命周期的组件,而Shiro并不仅仅可以用在Web环境,也可以用在普通的JavaSE环境中
  7. CacheManager:缓存控制器,来管理如用户,角色,权限等缓存的;因为这些数据基本上很少改变,放到缓存中后可以提⾼访问的性能;
  8. Cryptography:密码模块,Shiro 提高了一些常见的加密组件用于密码加密,解密等

2.Shiro官方快速启动

2.1 异常

UnknownAccountException 		//找不到用户
IncorrectCredentialsException	 //密码不正确 
LockedAccountException 			//用户被锁定
ExcessiveAttemptsException 		//密码重试超过次数
ExpiredCredentialsException	 	//密钥已过期

2.2 Shiro的Subject分析

Subject   currentUser   =   SecurityUtils.getSubject();   //获取当前subject
Session   session   =   currentUser.getSession();   //shiro的session
currentUser.isAuthenticated()   //是否认证
currentUser.getPrincipal()   //获取⽤用户对象
currentUser.hasRole("schwartz")   //是否有这个⻆角⾊色
currentUser.isPermitted("lightsaber:wield")   //是否有权限   #这个是我们后⾯面⽤用的最多的
currentUser.logout();   //注销认证

2.3 SpringBoot整合Shiro环境搭建

  1. 导入Shiro的POM
<dependency>
<groupId>org.apache.shiro</groupId>
<artifactId>shiro-spring</artifactId>
<version>1.4.2</version>
</dependency>
  1. Shiro配置
@Configuration
public   class   ShiroConfig   {

//ShiroFilterFactoryBean   3
@Bean
public   ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager{
	ShiroFilterFactoryBean   shiroBean   =   new   ShiroFilterFactoryBean();
	//设置安全管理器
	shiroBean.setSecurityManager(securityManager);
	return   shiroBean;
  }

//DefaultWebSecurityManager   2 
@Bean(name="securityManager")
public   DefaultWebSecurityManager getDefaultWebSecurityManager(@Qualifier("usrRm")UserRealm userRealm){
	DefaultWebSecurityManager   securityManager   =   new  DefaultWebSecurityManager();
	//关联Realm
	securityManager.setRealm(userRealm);//这样直接是不行的
	return   securityManager;
	}

//Realm   需要自定义   1
@Bean(name="usrRm")
public   UserRealm   userRealm(){
	return   new   UserRealm();
	}
}
  1. 自定义Realm
public   class   UserRealm   extends   AuthorizingRealm{

//授权
@Override
protected   AuthorizationInfo   doGetAuthorizationInfo(PrincipalCollection principalCollection) {
	System.out.println("执⾏了授权=》   AuthorizationInfo");
	return   null;
	}

//认证
@Override
protected   AuthenticationInfo   doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException{
	System.out.println("执⾏了认证=》   AuthenticationInfo");
	return   null;
	}
}

2.4 Shiro实现登录拦截

//ShiroFilterFactoryBean   3
@Bean
public   ShiroFilterFactoryBean getShiroFilterFactoryBean(@Qualifier("securityManager")DefaultWebSecurityManager securityManager{
	ShiroFilterFactoryBean   shiroBean   =   new   ShiroFilterFactoryBean();
	
	//设置安全管理理器器 
	shiroBean.setSecurityManager(securityManager);
	/**
	*   -   anon   :   ⽆无需认证就可以访问
	*   -   authc   :   必须认证才能访问
	*   -   user   :   必须开启rememberme后才能⽤用
	*   -   perms   :   拥有对某个资源权限才能访问
	*   -   role   :   拥有某个⻆角⾊色才能访问
	*/

	Map<String,String>   filterMap   =   new   HashMap<String,String>();

	filterMap.put("/*","anon");
	filterMap.put("/level1/*","authc");
	filterMap.put("/level2/*","authc");
	filterMap.put("/level3/*","authc");

	shiroBean.setFilterChainDefinitionMap(filterMap);
	
	//设置登录⻚页面
	shiroBean.setLoginUrl("/toLogin");
	return   shiroBean;
}

2.5 Shiro实现用户认证

	用户的认证应该放在Realm里进行
	Realm里两部分核心:授权、认证
  1. 先写controller获得用户名密码
@RequestMapping("/login")
public   String   login(String	username,String	password,Model	model){
	//获取当前⽤用户
	Subject   subject   =   SecurityUtils.getSubject();
	UsernamePasswordToken   token   =   new   UsernamePasswordToken(username, password);
	try   {
	subject.login(token);
	return   "index";
	}catch   (UnknownAccountException   uae)   {   //用户名不存在
	model.addAttribute("msg","⽤用户名不不存在!");
	return   "views/login";
	}   catch   (IncorrectCredentialsException   ice)   {
	model.addAttribute("msg","密码错误!");
	return   "views/login";
	}   catch   (Exception   ex){
	model.addAttribute("msg","未知登录异常!");
	return   "views/login";
} 
  1. Realm的强制认证
//认证
@Override
protected   AuthenticationInfo   doGetAuthenticationInfo(AuthenticationToken authenticationToken)throws  AuthenticationException{
	System.out.println("执⾏了认证=》   AuthenticationInfo");
	//没有连数据库,先伪造数据
	String   authName   =   "gaivn";
	String   authPwd   =   "123456";
	UsernamePasswordToken   userToken   =   (UsernamePasswordToken) authenticationToken;
	if(!authName.equals(userToken.getUsername())){
	return   null;
	}
	//这里只需要把密码传入就ok了了
	return   new   SimpleAuthenticationInfo("",authPwd,"");
}

3. Shiro集成mybatis进行权限验证

@Autowired
UserMapper   userMapper;

//认证
@Override
protected   AuthenticationInfo   doGetAuthenticationInfo(AuthenticationToken authenticationToken)throws   AuthenticationException{
	System.out.println("执⾏行行了了认证=》   AuthenticationInfo");

	UsernamePasswordToken   userToken   =   (UsernamePasswordToken) authenticationToken;
	UserInfo   userInfo   =   userMapper.queryUserForName(userToken.getUsername());

	if(userInfo==null){
	return   null;
	}
//这⾥只需要把密码传入就ok了
	return   new   SimpleAuthenticationInfo("",userInfo.getPassword(),"");
}

4. Shiro请求授权实现

//认证
@Override
protected   AuthenticationInfo   doGetAuthenticationInfo(AuthenticationTokenauthenticationToken) throws   AuthenticationException{
	System.out.println("执⾏行行了了认证=》   AuthenticationInfo");

	UsernamePasswordToken   userToken   =   (UsernamePasswordToken) authenticationToken;

	UserInfo   userInfo   =   userMapper.queryUserForName(userToken.getUsername());

	if(userInfo==null){
	return   null;
	}
	//这里只需要把密码传入就ok了了
	return   new   SimpleAuthenticationInfo(userInfo,userInfo.getPassword(),"");
}


//授权
@Override
protected   AuthorizationInfo   doGetAuthorizationInfo(PrincipalCollection principalCollection){
	System.out.println("执⾏行行了了授权=》   AuthorizationInfo");
	//定义一个授权
	//从DB⾥里里取,who?-》role
	SimpleAuthorizationInfo   info   =   new   SimpleAuthorizationInfo();
	Subject   subject   =   SecurityUtils.getSubject();
	UserInfo   userInfo   =   (UserInfo)   subject.getPrincipal();
	info.addStringPermission(userInfo.getRolename());
	return   info;
}

5. Thymeleaf集成Shiro

shiro:authenticated //已认证登录
shiro:notAuthenticated //未认证
shiro:hasPermission="level1:page" //是否有这个权限
<shiro:principal property="username"/> //输出我们的⽤用户名

<!--登录注销-->
<div   class="right   menu">
<!--未登录--> 
<div   shiro:notAuthenticated>
<a   class="item"   th:href="@{/toLogin}">
<i   class="address   card   icon"></i>   登录
</a>
</div>
<div   shiro:authenticated>
<a   class="item"   th:href="@{/logout}">
<i   class="address   card   icon"></i>   欢迎:
<shiro:principal   property="username"/>
</a>
</div>
<div   shiro:authenticated>
<a   class="item"   th:href="@{/logout}">
<i   class="address   card   icon"></i>   注销
</a>
</div>
</div>

<div   class="column"   shiro:hasPermission="level1:page">

//Realm   需要⾃自定义   1
@Bean(name="usrRm")
public   UserRealm   userRealm(){
	return   new   UserRealm();
}
//shiro集成thymeleaf的bean
@Bean
public   ShiroDialect   getShiroDialect(){
	return   new   ShiroDialect();
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值