浅析shiro框架的认证和授权

shiro安全框架

1.1.Shiro 概述

Shiro是apache旗下一个开源安全框架,它将软件系统的安全认证相关的功能抽取出来,实现用户身份认证,权限授权、加密、会话管理等功能,组成了一个通用的安全认证框架,使用shiro就可以非常快速的完成认证、授权等功能的开发,降低系统成本。
课后了解:Spring security 安全框架

1.2.Shiro 概要架构

在概念层,Shiro 架构包含三个主要的理念:Subject,SecurityManager和 Realm。

1.3shiro的构件

1)Subject(主体):与软件交互的一个特定的实体(用户、第三方服务等)。
2)SecurityManager(安全管理器) :Shiro 的核心,用来协调管理组件工作。
3)Authenticator(认证管理器):负责执行认证操作
4)Authorizer(授权管理器):负责授权检测
5)SessionManager(会话管理):负责创建并管理用户 Session 生命周期,提供一个强有力的 Session 体验。
6)SessionDAO:代表 SessionManager 执行 Session 持久(CRUD)动作,它允许任何存储的数据挂接到 session 管理基础上。
7)CacheManager(缓存管理器):提供创建缓存实例和管理缓存生命周期的功能
8)Cryptography(加密管理器):提供了加密方式的设计及管理。
9)Realms(领域对象):是shiro和你的应用程序安全数据之间的桥梁。

2.1Shiro 认证

简述:
1)系统调用subject的login方法将用户信息提交给SecurityManager
2)SecurityManager将认证操作委托给认证器对象Authenticator
3)Authenticator将身份信息传递给Realm。
4)Realm访问数据库获取用户信息然后对信息进行封装并返回。
5)Authenticator 对realm返回的信息进行身份认证。

详述:
用户名密码验证为例,当浏览器客户端向服务器发送AJAX异步请求,请求服务器处理验证用户输入的用户名和密码,
当请求传入Tomcat,通过Tomcat的过滤器****到达前端控制器的时候,前端控制器截取请求的url,在HandlerMapping里找对应的map集合中的entry元素,找到后穿过springMVC的拦截器到达后端控制器Controller,在Controller里使用SecorityUtils获取一个Subject,subject里面有一个login方法,但是调用login方法必须传入一个token类型的参数,这时候我们想到AJAX里面传过来的username和password正好可以封装在一个UsernamePasswordtoken里面,所以我们这样写

UsernamePasswordToken tokensubjec = new UsernamePasswordToken(username,password);
Subject subject = SecurityUtils.Subject();
subject.login(token);

当我们写完这句subject.login(token);
系统底层会帮我们从配置文件读取我们配置的SecurityManager以及相关配置,并将token传过去,会找到anthenticator(认证管理器),anthenticator根据SecurityManager里面配置的realm,找到realm。我们要做的就是在这之前一定要确保该realm已经存在,否则会找不到,在realm中我们将传过来token进行向下造型回usernamepasswordtoken,
然后将里面的username取出来传递到数据层,让数据层根据username从用户名中查询具体用户所有信息,查询完毕我们使用一个SimpleAuthenticationInfo进行信息封装,new一个该对象的时候我们要传入四个参数第一个是身份信息,我们一般传入从dao数据层查到的用户信息,但是要注意这里写入的类型和授权的时候取数据的类型要对应,如果只写用户名则取数据的时候用字符串接收,第二个参数是加密后的密码,我们已经查到,第三个参数是指定类型的salt,其实和我们通过数据层查到的salt是一样的只不过需要的类型不一致,需要做一步转型即可,第四个参数是realm的名字,表示本类直接用this.getName();然后将我们new出来的SimpleAuthenticationInfo对象的实例返回给认证管理器,认证管理器会自动帮我们认证。
如下图所示浅析shiro框架的认证和授权_第1张图片

2.2Shiro的授权

概述:
1)系统调用subject相关方法将用户信息(例如isPermitted)递交给SecurityManager
2)SecurityManager将权限检测操作委托给Authorizer对象
3)Authorizer将用户信息委托给realm.
4)Realm访问数据库获取用户权限信息并封装。
5) Authorizer对用户授权信息进行判定。

3.基于注解的方式配置Shiro组件

@Bean("securityManager")
public DefaultWebSecurityManager  newDefaultWebSecurityManager(
			AuthorizingRealm userRealm){
		DefaultWebSecurityManager sManager=
		new DefaultWebSecurityManager();
		//此时必须保证realm对象已经存在了
		sManager.setRealm(userRealm);
		return sManager;
}


@Bean("shiroFilterFactoryBean")
public ShiroFilterFactoryBean newShiroFilterFactoryBean(
			SecurityManager securityManager){//shiro 包
		ShiroFilterFactoryBean bean=new ShiroFilterFactoryBean();
		bean.setSecurityManager(securityManager);
	    //当此用户是一个非认证用户,需要先登陆进行认证
		bean.setLoginUrl("/doLoginUI.do");
		LinkedHashMap fcMap=
		new LinkedHashMap<>();
		fcMap.put("/bower_components/**","anon");//anon表示允许匿名访问
		fcMap.put("/build/**", "anon");
		fcMap.put("/dist/**","anon");
		fcMap.put("/plugins/**","anon");
		fcMap.put("/doLogin.do","anon");
		fcMap.put("/doLogout.do","logout");
		fcMap.put("/**", "authc");//必须授权才能访问
		bean.setFilterChainDefinitionMap(fcMap);
		return bean;
}


@Bean("lifecycleBeanPostProcessor")
public LifecycleBeanPostProcessor newLifecycleBeanPostProcessor(){
		return new LifecycleBeanPostProcessor();
}


@DependsOn(value="lifecycleBeanPostProcessor")
@Bean
public DefaultAdvisorAutoProxyCreator newDefaultAdvisorAutoProxyCreator(){
		return new DefaultAdvisorAutoProxyCreator();
}


@Bean
public AuthorizationAttributeSourceAdvisor newAuthorizationAttributeSourceAdvisor(
			SecurityManager securityManager){
		    AuthorizationAttributeSourceAdvisor bean=
			new AuthorizationAttributeSourceAdvisor();
		    bean.setSecurityManager(securityManager);
		return bean;
	}


3.3.Shiro 核心过滤器配置
在注解启动类中,重写onStartup方法,完成过滤器的注册
	@Override
	public void onStartup(ServletContext servletContext) 
throws ServletException {
		System.out.println("onStartup");
		//super.onStartup(servletContext);
		registerContextLoaderListener(servletContext);
		registerFilter(servletContext);
		registerDispatcherServlet(servletContext);
	}

	private void registerFilter(ServletContext servletContext) {
		//注册Filter对象
		//项目没有web.xml并且此filter不是自己写的,所以需要用这种配置方式
		FilterRegistration.Dynamic dy=
		servletContext.addFilter("filterProxy",
				DelegatingFilterProxy.class);
		dy.setInitParameter("targetBeanName","shiroFilterFactoryBean");
		dy.addMappingForUrlPatterns(
				null,//EnumSet
				false,"/*");//url-pattern
	}

4.基于xml方式配置Shiro组件




	
	
		
		
		
	
	
	
	
	
	
	
	
	
		
	

	
	
	
		
		
		
		
			
				
				
				
				
				
				
				
				
			
		
	

web.xml



  CGB-JT-SYS-V1.01
  
  
     shiroFilter
     org.springframework.web.filter.DelegatingFilterProxy
     
        targetBeanName
        shiroFilterFactory
     
  
  
     shiroFilter
     /*
  
  
  
  
  
       frontController
       org.springframework.web.servlet.DispatcherServlet
       
          contextConfigLocation
          classpath:spring-configs.xml
        
       
       1
 
 
 
      frontController
      *.do
 
 

你可能感兴趣的:(shiro)