编程语言
首页 > 编程语言> > java学习day60--Shiro安全框架

java学习day60--Shiro安全框架

作者:互联网

目录

Shiro安全框架

Shiro概述

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

​ 用户在进行资源访问时,要求系统要对用户进行权限控制,其具体流程如图

1595773223432

Shiro概要架构

1595773263354

说明:

Subject :主体对象,负责提交用户认证和授权信息。
SecurityManager:安全管理器,负责认证,授权等业务实现。
Realm:领域对象,负责从数据层获取业务数据。

Shiro详细架构

​ Shiro框架进行权限管理时,要涉及到的一些核心对象,主要包括:认证管理对象,授权管理对象,会话管理对象,缓存管理对象,加密管理对象以及Realm管理对象(领域对象:负责处理认证和授权领域的数据访问题)等

Shiro框架认证拦截实现(filter)

Shiro基本环境配置

添加shiro依赖

实用spring整合shiro时,需要在pom.xml中添加如下依赖

<dependency>
   <groupId>org.apache.shiro</groupId>
   <artifactId>shiro-spring</artifactId>
   <version>1.5.3</version>
</dependency>

Shiro核心对象配置

​ 基于SpringBoot 实现的项目中,没有提供shiro的自动化配置,需要我们自己配置。

第一步:创建SpringShiroConfig类。

第二步:在Shiro配置类中添加SecurityManager配置(这里一定要使用org.apache.shiro.mgt.SecurityManager这个接口对象)

第三步: 在Shiro配置类中添加ShiroFilterFactoryBean对象的配置。通过此对象设置资源匿名访问、认证访问。

package com.cy.pj.common.config;

/** @Configuration 注解描述的类为spring框架中的一个配置类  */
@Configuration
public class SpringShiroConfig {
    /**
     * SecurityManager 对象shiro框架的核心。
     * @Bean 通常会配置@Configuration注解进行使用,其它特点:
     * 1)此注解描述方法会交给spring管理
     * 2)@Bean注解没有指定其value属性的值,则bean的名字默认为方法名
     * @return
     */
	//@Bean(value="sManager")
	@Bean
	public SecurityManager securityManager(Realm realm,
			CacheManager cacheManager,
			RememberMeManager rememberManager,
			SessionManager sessionManager) {
		DefaultWebSecurityManager sManager=new DefaultWebSecurityManager();
		sManager.setRealm(realm);
		sManager.setCacheManager(cacheManager);
		sManager.setRememberMeManager(rememberManager);
		sManager.setSessionManager(sessionManager);
		return sManager;
	}
	/**
	 * Spring容器在管理ShiroFilterFactoryBean对象,
	 *    会基于ShiroFilterFactoryBean对象, 创建过滤器工厂对象(SpringShiroFilter),
	 *    然后通过过滤器工厂创建过滤器(filter)对象,最后通过Filter对请求数据进行过滤,
	 *    例如调用securityManager的方法判定此请求是否已经过认证,假如没有经过认证
	 *    则跳转到登陆页面进行认证即可。
	 * @param securityManager
	 * @return
	 */
	@Bean
	public ShiroFilterFactoryBean shiroFilterFactory(SecurityManager securityManager) {
		ShiroFilterFactoryBean fBean=new ShiroFilterFactoryBean();
		fBean.setSecurityManager(securityManager);
		//设置需要进行认证的登陆页面
		fBean.setLoginUrl("/doLoginUI");
		//设置过滤规则(有顺序,允许匿名访问的放在上面)
		LinkedHashMap<String,String> filterMap=new LinkedHashMap<>();
		filterMap.put("/bower_components/**","anon");//anno为shiro框架定义,会对应一个过滤器对象,这里表示允许匿名访问
		filterMap.put("/build/**","anon");
		filterMap.put("/dist/**","anon");
		filterMap.put("/plugins/**","anon");
		filterMap.put("/user/doLogin", "anon");//登陆操作允许匿名访问
		filterMap.put("/doLogout", "logout");//logout为登出操作,此操作执行时会进入登陆页面
		//filterMap.put("/**", "authc");//authc为设置需要认证访问的资源
		filterMap.put("/**", "user");//user表示可以通过用户端提交的cookie信息进行认证
		fBean.setFilterChainDefinitionMap(filterMap);
		return fBean;
	}

过滤器名称

1595776495172

对象关系如下图

1595776586117

Shiro登陆页面呈现

服务端Controller实现

客户端页面实现

Shiro框架认证业务实现

认证流程分析

​ 身份认证即判定用户是否是系统的合法用户,用户访问系统资源时的认证(对用户身份信息的认证)

其中认证流程分析如下:

思考:不使用shiro框架如何完成认证操作?filter,intercetor。

认证服务端实现

认证核心业务分析

1595809590848

DAO接口定义

Mapper元素定义

Service接口及实现

Controller 类实现

认证客户端实现

异步登陆操作实现

点击登录操作时,将输入的用户名,密码异步提交到服务端。在login.html页面中

<script>
    $(function () {
    $('input').iCheck({
        checkboxClass: 'icheckbox_square-blue',
        radioClass: 'iradio_square-blue',
        increaseArea: '20%' // optional
    });
    $(".btn").click(doLogin);
});
function doLogin(){
    var params={
        username:$("#usernameId").val(),
        password:$("#passwordId").val(),
        isRememberMe:$("#rememberId").prop("checked")
    }
    var url="user/doLogin";
    console.log("params",params);
    $.post(url,params,function(result){
        console.log("login.result",result);
        if(result.state==1){
            //跳转到indexUI对应的页面
            location.href="doIndexUI?t="+Math.random();
        }else{
            $(".login-box-msg").html(result.message); 
        }
        return false;//防止刷新时重复提交
    });
}
</script>

退出操作配置实现

在SpringShiroConfig配置类中,修改过滤规则,添加以下过滤即可

filterMap.put("/doLogout", "logout");

Shiro框架授权过程实现

授权流程分析

授权即对用户资源访问的授权(是否允许用户访问此资源)

1595854780215

其中授权流程分析如下:

不使用shiro如何完成授权操作?intercetor,aop。

添加授权配置

在SpringShiroConfig配置类中,添加授权时的相关配置:

第一步:配置bean对象的生命周期管理(SpringBoot可以不配置)

//配置bean对象的生命周期管理
@Bean
public LifecycleBeanPostProcessor lifecycleBeanPostProcessor () {
    return new LifecycleBeanPostProcessor();
}

第二步: 通过如下配置要为目标业务对象创建代理对象(SpringBoot中可省略)

@DependsOn("lifecycleBeanPostProcessor")
@Bean
public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
		 return new DefaultAdvisorAutoProxyCreator();
}

第三步:配置advisor对象,shiro框架底层会通过此对象的matchs方法返回值(类似切入点)决定是否创建代理对象,进行权限控制。

//配置Advisor对象,此对象内容会关联切入点和相关通知
@Bean
public AuthorizationAttributeSourceAdvisor 
authorizationAttributeSourceAdvisor (
	    		    SecurityManager securityManager) {
		        AuthorizationAttributeSourceAdvisor advisor=
				new AuthorizationAttributeSourceAdvisor();
advisor.setSecurityManager(securityManager);
	return advisor;
}

授权服务端实现

核心业务分析

1595855415824

Dao实现

Mapper实现

Service实现

/**
 *  	完成授权信息的获取和封装
 */
@Override
protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {

    //获取登录用户信息 例如id
    SysUser sysUser =(SysUser)principals.getPrimaryPrincipal();//主身份,基于认证传的信息
    Integer userId  = sysUser.getId();
    //基于用户的id获取用户所拥有的角色
    List<Integer> roleIds = sysUserRoleDao.findRoleIdsByUserId(userId);
    if (roleIds==null || roleIds.size()==0) {
        throw new AuthorizationException();
    }
    //基于角色id 获取对应的菜单id
    List<Integer> menuIds =sysRoleMenuDao.findMenuIdsByRoleIds(roleIds);
    if (menuIds==null || menuIds.size()==0) {
        throw new AuthorizationException();
    }
    //基于菜单id 获取权限标识
    List<String> permissions = sysMenuDao.findPermissions(menuIds);
    if (permissions==null || permissions.size()==0) {
        throw new AuthorizationException();
    }
    //对权限标识信息进行封装并返回
    Set<String> set = new HashSet<>();
    for (String per : permissions) {
        if (!StringUtils.isEmpty(per)) {
            set.add(per);
        }
    }
    //System.out.println("set:"+set);
    SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
    //这里不可以使用构造方法赋值,必须要通过set方法
    info.setStringPermissions(set);
    return info;
}

授权访问实描述现

​ 在需要进行授权访问的业务层(Service)方法上,添加执行此方法需要的权限标识,参考代码@RequiresPermissions(“sys:user:update”)

只有在哪个方法上面使用了该注解,那么才会对该方法使用权限的控制

@RequiresPermissions注解的说明

/**
* @RequiresPermissions 这个注解描述的方法为一个切入点方法。此方法在执行之前
*    需要进行权限检测(负责这个过程的方法是一个通知方法),假如用户权限中包含
 * @RequiresPermissions 注解value属性指定的值,则授权访问,不包含则抛出异常。
*   思考:假如你去设计这个切入点对应的通知方法,你会做什么?
	 *1)目标方法执行之前获取方法上的@RequiresPermissions注解,进而取到注解中内容。
 	 *2)将注解中内容提交(subject.checkPermission(perstr))给SecurityManager对象(此对象负责授权操作)
	  *3)SecurityManager会基于realm去查找用户拥有的权限(这部分我们自己实现)。
	  *4)SecurityManager会判断用户拥有权限中是否包含RequiresPermissions注解中的内容
	  *5)SecurityManager基于用户权限进行授权或抛出异常。
	 */

说明:此要注解一定要添加到业务层方法上。

标签:java,--,用户,认证,day60,对象,shiro,id,Shiro
来源: https://www.cnblogs.com/liqbk/p/13388385.html