shiro

shiro


前言

shiro数据安全控制


提示:以下是本篇文章正文内容,下面案例可供参考

一、shiro是什么

shiro安全框架: shiro是做网页数据安全的一种框架,比如,在访问某个网站时没有登录的情况下是不能访问别的网页

类似的产品:spring security, 学习成本过高,过于复杂,控制粒度细
shiro框架相对简单,足够应用在企业级项目中
springmvc中的拦截器,也可以做到安全管理,比shiro还简单

shiro安全框架能做什么:
主要的功能:
登录认证:shiro 登入
通过shiro做登录操作,如果没有登录成功,就跳转到登录页面
如果登录成功了,就跳转到指定的页面,而且还可以访问项目中
其他的敏感资源(项目中的所有的功能都能访问),就是用户访问
项目中的任何资源都要通过shiro检测是否登录

权限认证:
  根据用户权限的不同,登录完后显示的主页菜单中菜单项也不同
  比如:
     超级管理员权限的账号,能够在主页面中显示所有的菜单项(10个)
	 普通权限的账号,指定显示3个菜单项

二.shiro使用流程

shiro的全模块功能:
primary concerns:
Authentication:登录认证
AUthorization:授权认证
Session Management:session管理 可以用此session共享数据 shiro登出
Cryptography:加密管理

spportting features:支持的特性
web support:shiro支持web项目
caching:使用shiro的缓存机制,缓存数据
Concurrency:支持高并发
testing:支持测试
run as :支持java项目
remember me:支持记住我

shiro的工作流程图:参见shiro工作流程图.png
在这里插入图片描述

application code:应用程序的代码,最终对应的一个方法,此方法用来启动shiro;
这个方法可以用某一个线程调用
subject:subject英文原义就主题,标题,在shiro中理解成 current user 当前用户
可以理解成某一个用户在操作一个主题
某一个线程在操作一个主题
shiro securitymanager:shiro的安全管理器(安全管理中心)
管理所有subject
realm:英文原义就是领域,范围,
可以理解成数据库中的数据,或文件中的数据,总之是数据源.

文字版的shiro的工作流程:
用户输入用户名和密码,通过shrio把用户的名和密码,存储给subject
subject携带数据给安全管理中心,安全管理中心管理所有的subject
安全管理中心回调AuthorizingRealm类或实现Authorizer接口中的方法,有两个方法
登录认证:protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException
权限认证:protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals)
在登录认证中指定如何从数据库中获取数据库的真实用户登录数据(realm),然后realm数据给安全管理中即可
在权限认证中指定如果从数据库中获取数据库的真实的权限数据(realm),然后把realm数据给安全管理中心即可
总之,用户写好回调的策略方法,由安全管理中心回调
回调方法是有顺序的先回调登录认证,后回调权限认证
最后由安全管理中心负责判断并跳转.

其实shiro的底层用的是动态代理:
//环绕通知,能够控制业务方法的执行
public Object around(ProceedingJoinPoint pjp){
Object returnValue=null;
try{
//前置通知
if(登录过){
returnValue=pjp.proceed();//调用目标方法
}else{
//跳转到登录页面
//页面的名称配置到spring_shiro.xml中
}
//后置通知
}catch(Exception e){
//异常通知
}finally{
//最终通知
}
return returnValue;
}

三、使用步骤

1.配置文件

1.导入jar包
 <!-- Apache Shiro 权限依赖 -->
		<dependency>
			<groupId>org.apache.shiro</groupId>
			<artifactId>shiro-all</artifactId>
			<version>1.2.3</version>
		</dependency>
		<!-- spring aop 依赖 -->
		<dependency>
		  <groupId>org.springframework</groupId>
		  <artifactId>spring-aop</artifactId>
		  <version>4.3.7.RELEASE</version>
		</dependency>

		<dependency>
		  <groupId>org.aspectj</groupId>
		  <artifactId>aspectjweaver</artifactId>
		  <version>1.8.7</version>
		</dependency>

在maven项目里的src/main/resources的文件家里创建一个conf文件夹,里面创建一个spring_shiro.xml文件里面代码如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:p="http://www.springframework.org/schema/p"
	xmlns:util="http://www.springframework.org/schema/util" 
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:mvc="http://www.springframework.org/schema/mvc"
	xsi:schemaLocation="
        http://www.springframework.org/schema/beans
        http://www.springframework.org/schema/beans/spring-beans.xsd
        http://www.springframework.org/schema/aop 
        http://www.springframework.org/schema/aop/spring-aop.xsd
        http://www.springframework.org/schema/tx 
        http://www.springframework.org/schema/tx/spring-tx.xsd
        http://www.springframework.org/schema/util 
        http://www.springframework.org/schema/util/spring-util.xsd
        http://www.springframework.org/schema/context
        http://www.springframework.org/schema/context/spring-context.xsd
        http://www.springframework.org/schema/mvc
        http://www.springframework.org/schema/mvc/spring-mvc.xsd">
	
   <!--将Shiro的组件以bean的形式交给Spring管理  -->
	 <bean id="lifeCycleBeanProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"></bean>
	 
	<!--Spring为shiro的bean创建代理对象 
		代理的方式:
			1.jdk
			2.cglib
	 -->
	 <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator"
	 		depends-on="lifeCycleBeanProcessor">
	 	<!--表示强制使用cglib为其创建代理对象  -->
	 	<property name="proxyTargetClass" value="true"></property>
	 </bean>
	
	
	<!--切面中需要的对象,也使用cglib来创建代理对象  -->
	<aop:aspectj-autoproxy proxy-target-class="true"></aop:aspectj-autoproxy>
  	
  	
  	<!--Shiro的安全中心  其中需要提供真实的用户信息. 需要加载realm  -->
	 <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager">
	 	
	 	<property name="realm" ref="AuthRealm"></property>
	 </bean>
	 
	 <!--自定义Realm 为安全中心提供信息  -->
	 <bean id="AuthRealm" class="cn.tedu.shiro.AuthRealm">
	 	<property name="credentialsMatcher" ref="authCredential"></property>
	 </bean>
	 
	 
	 <!--自定义加密算法  -->
	 <bean id="authCredential" class="cn.tedu.shiro.AuthCredential"/>
	 
	
	 <!--权限认证的适配器  -->
	 <bean  class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor">
	 	<property name="securityManager" ref="securityManager"></property>
	 </bean>
	 <!--创建一个logoutFilter对象,shiro登出  -->
	 <bean id="logoutFilter" class="cn.tedu.shiro.SystemLogoutFilter">
	 	<property name="redirectUrl" value="/login.html"></property>
	 </bean>
	 
	 <!-- shiro的过滤器  -->
	 <bean id="shiroFilter"  class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
	 	<!--配置安全中心  -->
	 	<property name="securityManager" ref="securityManager"></property>
	 	
	 	<!--指定登陆的地址  当用户没有登陆时.默认跳转该页面-->
	 	<property name="loginUrl" value="/login.html"></property>
	 	
	 	<!-- 注册shiro的过滤器 -->
	 	<property name="filters">
	 		<map>
	 			<!-- 注册登出的过滤器给shiro过滤器 -->
	 			<entry key="logout" value-ref="logoutFilter"></entry>
	 		</map>
	 	</property>
	 	
	 	<!--过滤器链  -->
	 	<property name="filterChainDefinitions">
		 	<value>
		 		<!--添加过滤信息
		 			1.anon  表示放行
		 			2.authc 表示拦截-->
			 	/user/login = anon
			 	/css/**  = anon
			 	/font-awesome/**  = anon
			 	/fonts/**  = anon
			 	/head/**  = anon
			 	/images/**  = anon
			 	/js/**  = anon
			 	/page/**  = anon
			 	<!-- 请求user/logout地址,shiro会调用过滤器中的preHandle -->
			 	/user/logout=logout
			 	<!--/** 拦截所有的请求和静态资源文件  -->
		        /index.html* = authc
		        /index.jsp* = authc
			 	/** = authc
		 	</value>
	 	</property>
	 </bean>
</beans>

3.创建两个类
a.此类继承自AuthoriaingRealm类
重写两个方法
登录认证
权限认证

package cn.tedu.shiro;


import java.util.List;

import javax.annotation.Resource;

import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authc.UsernamePasswordToken;
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 org.apache.shiro.subject.Subject;

import cn.tedu.dao.UserMapper;
import cn.tedu.entity.User;

public class AuthRealm extends AuthorizingRealm {
	@Resource
	private UserMapper userMapper;
	//权限认证的回调方法
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
		System.out.println("权限认证");
		// 得到用户对象
		 Subject subject = SecurityUtils.getSubject();
		 String loginName = subject.getSession().getAttribute("loginName").toString();
		// 根据用户名查询角色信息
		 List<String> moduleName=userMapper.findModulesByLoginName(loginName);
		// List<String> roleList = userService.findRoleByUserName(username);

		/*
		 * List<String> roleList = new ArrayList<String>(); roleList.add("用户管理");
		 * roleList.add("课程管理"); roleList.add("视频管理");
		 */
		// 创建授权管理
		SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();

		// 传入授权管理的集合信息
		info.addStringPermissions(moduleName);
		return info;
	}

	@Override
	// 登陆认证回调方法
	protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
		System.out.println("登录认证");
		 UsernamePasswordToken loginToken =(UsernamePasswordToken) token;
		String loginName = loginToken.getUsername(); 
		User user =userMapper.findUserByUserLoginName(loginName);
		
		/*
		 * principal:主要的; 本金的; 最重要的; 资本的; 真实的对象 
		 * credentials:凭证,证件; 表示真实的密码 
		 * realmName:域,范围的名字 当前的realm
		 */
		  
		  AuthenticationInfo info = new SimpleAuthenticationInfo(user,user.getPassword(),this.getName());
		
		return info;

	}

}

b.此类继承自SimpleCredentialsMatcher类
重写一个方法,指定密码的加密原则

package cn.tedu.shiro;

import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.SimpleCredentialsMatcher;
/**
 * 这是一个加密的回调方法
 * @author Mechrev
 *
 */
public class AuthCredential extends  SimpleCredentialsMatcher{
	
	@Override
	public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
		//通过token 获取用户名和密码
		UsernamePasswordToken userToken = (UsernamePasswordToken) token;
		/*String username = userToken.getUsername();
		String password = String.valueOf(userToken.getPassword());
		
		String encryptPassword = Encrypt.getMd5(password, username);
		userToken.setPassword(encryptPassword.toCharArray());*/
		
		return super.doCredentialsMatch(userToken, info);
	}
}

分析用shiro登录和不用shiro登录的区别
不用shiro:
select user_id from t_user
where user_loginname=? and user_password=?

<!-- 非shiro登录 -->
	<select id="login"
	        parameterType="User"
	        resultType="java.lang.String">
		select
		    user_id
		from t_user
		where user_loginname=#{loginName} and
		      user_password=#{password}        
	</select>
优点:访问数据库一次,能完成登录业务
缺点:不能防护除登录外的其他的敏感资源,要想防护,必须借助spirng mvc拦截器
<!-- shiro登录 -->
	<select id="findUserByUserLoginName" parameterType="java.lang.String" resultType="User">
		select
			user_id id,
			user_loginname loginName,
			user_password password
		from t_user
		where user_loginname=#{loginName}
	</select>
优点:访问数据库一次,能够完成登录,可以防护敏感资源
缺点:性能堪忧,因为每一次url请求资源,都要经过shiro的安全管理来判断是否是登录用户

2.读入数据

代码如下(示例):

data = pd.read_csv(
    'https://labfile.oss.aliyuncs.com/courses/1283/adult.data.csv')
print(data.head())

该处使用的url网络请求的数据。


总结

使用shiro可以对敏感资源进行保护: 使用shiro:在polm文件导入依赖 在xml里创建shiro的配置文件 创建两个类1.进行登录的验证,和权限的验证 2.进行对密码的加密
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值