shiro 框架之 加密处理。
一、shiro 加密?
/*
Shiro?
一、为什么要加密?
为调高数据库的安全性,需要给密码加密。
二、常见的加密算法?
1.1哈希算法
md5:加密算法 哈希函数
1.2.对称算法
1.3.非对称算法
三、如何进行加密后的匹配?
注册用户-----获取用户对象----密码加密---存数据库
四.如何匹配?
对密码先加密----匹配
token :前台穿过来的密码(未加密)
join:数据库中已经加密的密码
*/
二、实现。
在shiro.xml中1.开启密码匹配器
2.logout 注销 设置一个注销的方法,可以清除session中缓存。
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> <!--1.安全管理器--> <bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <!--缓存管理器 暂时不引用他--> <!--<property name="cacheManager" ref="cacheManager"/>--> <!--会话的模式--> <property name="sessionMode" value="native"/> <!--配置realm --> <property name="realm" ref="myRealm"/> </bean> <!--2.缓存管理器--> <bean id="cacheManager" class="org.apache.shiro.cache.ehcache.EhCacheManager"> </bean> <bean id="myRealm" class="com.aaa.realm.MyRealm"> <property name="name" value="myRealm"/> <!--3.品证(密码)匹配器--> <property name="credentialsMatcher"> <bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"> <!--加密算法的名称 --> <property name="hashAlgorithmName" value="MD5"/> <!-- 是否让它 进行16进制的编码 --> <property name="storedCredentialsHexEncoded" value="true"/> <!-- 迭代的次数 123。。。。加密 。。。。加密 1024 次 叫做迭代。 --> <!--<property name="hashIterations" value="1024"/>--> </bean> </property> </bean> <!--4.shiro中的类型要交给 spring容器管理的bean--> <bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/> <!--5.启用注解配置--> <bean class="org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator" depends-on="lifecycleBeanPostProcessor"/> <bean class="org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor"> <property name="securityManager" ref="securityManager"/> </bean> <!-- 6. shiro 的过滤器 id和名字保持一致 和web.xml 中过滤器的名字保持一致。否则配置没有效果。 --> <bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"> <!--1.引入安全管理器 --> <property name="securityManager" ref="securityManager"/> <!--2.登录的地址 --> <property name="loginUrl" value="/login.jsp"/> <!--3.登录成功的页面 --> <property name="successUrl" value="/index.jsp"/> <!--4.绑定一个未授权的路径。--> <property name="unauthorizedUrl" value="/unauthorized.jsp"/> <!-- <property name="filters"> <util:map> <entry key="aName" value-ref="someFilterPojo"/> </util:map> filterChainDefinitions 过滤器的规则声明。 1.anon 匿名不需要验证 2. authc 认证 需要登录 3.perms 权限 4.logout 注销 设置一个注销的方法,可以清楚session中缓存。 /admin/** = authc 下的路径都需要进行登录认证 从上到下 前面规定好的 冲突就是优先级。 </property> --> <property name="filterChainDefinitions"> <value> /login.jsp = anon /index.jsp = anon /static/** =anon /logout=logout # allow WebStart to pull the jars for the swing app: /*.jar = anon # everything else requires authentication: /dept/**=authc /admin/** = authc </value> </property> </bean> </beans>
3.index.jsp 添加注销的超链连。
<%-- Created by IntelliJ IDEA. User: Administrator Date: 2019/8/5 Time: 10:04 To change this template use File | Settings | File Templates. --%> <%@ page contentType="text/html;charset=UTF-8" language="java" %> <html> <head> <title>mvc</title> </head> <body> <a href="view/addcaidan.jsp">菜单录入</a><br> <a href="admin/empdemo.jsp">admin路径下的 员工管理的查询 录入 删除</a><br> <a href="admin/empdemo1.jsp">admin路径下的 员工系统的增删改查</a><br> <a href="admin/wenjianshangchuang.jsp">admin路径下的 通过表单上传数据</a><br> <a href="view/wenjiango.jsp"> 单个文件</a><br> <a href="login.jsp"> 登录验证测试</a><br> <a href="view/duowenjian.jsp"> 多文件上传</a><br> <%-- 在shiro中配置一个注销的设置 在首页直接点击注销 就能注销session--%> <a href="logout">注销</a><br> </body> </html>
三、简单的加密方式?
2.1token 前台传过来的密码是没有加密的,通过shiro去加密,然后再匹配。
2.2info 中的原始密码,通过加密的方式,加密,得到一列字符串
2.3 在这里 我只对密码进行了限制是 666 ,用户名,可以随便输入
package com.aaa.realm; import org.apache.shiro.authc.*; import org.apache.shiro.crypto.hash.SimpleHash; import org.apache.shiro.realm.AuthenticatingRealm; import org.apache.shiro.util.ByteSource; /*1.编码实现realm类 * 2.继承AuthenticatingRealm * * 3.返回一个实现类 验证交给shiro * * realm * * 1.获取subject传递过来的token * 2.根据token中的用户名,找到密码 * 3.返回认证的对象。 * */ public class MyRealm extends AuthenticatingRealm { @Override //令牌信息 从表单中传递过来的身份信息 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken usernamePasswordToken= (UsernamePasswordToken) authenticationToken; //获取令牌中的用户名 String username = usernamePasswordToken.getUsername(); //连接数据库 进行查询操作 根据用户名 查询密码 模拟密码 // String password="666"; String password="fae0b27c451c728867a567e8c1bb4e53"; //数据库中加密后的密码 模拟获取 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,password,getName()); return info; } public static void main(String[] args) { // String username="admin"; // String password="123"; //算法的名称 和 原始密码 SimpleHash simpleHash = new SimpleHash("MD5","666" ); //得到 加密后的数据 fae0b27c451c728867a567e8c1bb4e53 String s = simpleHash.toHex(); System.out.println(s); } }
四。增添盐值 salt ,根据名字进行加密。
为什么?
在数据库中,不同的用户,可能存在相同的密码,这也是不安全的。---------》salt解决问题。
package com.aaa.realm; import com.aaa.util.MD5Utils; import org.apache.shiro.authc.*; import org.apache.shiro.crypto.hash.SimpleHash; import org.apache.shiro.realm.AuthenticatingRealm; import org.apache.shiro.util.ByteSource; public class MyRealm extends AuthenticatingRealm { @Override //令牌信息 从表单中传递过来的身份信息 protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException { UsernamePasswordToken usernamePasswordToken= (UsernamePasswordToken) authenticationToken; //获取令牌中的用户名 String username = usernamePasswordToken.getUsername(); String password="0668410aa0944d32908ca1fd66890c92"; //数据库中加密的密码 // 1.这里也要加上盐值 和下面匹配。 2.用户名充当盐值,不固定,不要把用户名写死。 username代替。 ByteSource salt = ByteSource.Util.bytes(username); //返回认证信息 添加一个 密码加密 salt 用户名 散列的密码 盐值,用户名 SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(username,password,salt,getName()); return info; } public static void main(String[] args) { //模拟数据库中的一个用户名 String username="haha"; //加盐,salt 类型是ByteSource 解决不同用户名密码相同的问题。 ByteSource salt = ByteSource.Util.bytes("haha"); //算法的名称 和 原始密码 盐值 SimpleHash simpleHash = new SimpleHash("MD5","666" ,salt); //得到 加密后的数据 0668410aa0944d32908ca1fd66890c92 String s = simpleHash.toHex(); System.out.println(s); } }
五,测试。