目录

今天的知识是与上次所分享的知识相关联的,在Shiro入门的基础进行编写,上次之前的数据是死数据(放在Shiro.ini)而这次是活数据,可以连接到数据库,运用域Relam知识。同时出于维护用户的经济利益,保护数据的安全,我们会使用md5对密码进行加密

一、Shiro认证(ssm)

1.  导入pom依赖

2、在web容器配置文件中 配置过滤器

3、使用mybatis逆向生成工具生成我们所需要的表的model和mapper

4、在userMapper.xml中映射根据用户名查找的方法

5、在mapper与业务层中添加方法

6、自定义域 Myrealm继承域

7、配置spring与shiro的集成文件

二、密码加盐加密


今天的知识是与上次所分享的知识相关联的,在Shiro入门的基础进行编写,上次之前的数据是死数据(放在Shiro.ini)而这次是活数据,可以连接到数据库,运用域Relam知识。同时出于维护用户的经济利益,保护数据的安全,我们会使用md5对密码进行加密

一、Shiro认证(ssm)

目的:将死数据变为数据库中的数据

实现步骤:

1.  导入pom依赖

   <!--shiro依赖--><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>1.3.2</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-web</artifactId><version>1.3.2</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>1.3.2</version></dependency>

2、在web容器配置文件中 配置过滤器

过滤器的作用:拦截所有请求并交给Shiro进行处理

<!-- shiro过滤器定义 --><filter><filter-name>shiroFilter</filter-name><filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class><init-param><!-- 该值缺省为false,表示生命周期由SpringApplicationContext管理,设置为true则表示由ServletContainer管理 --><param-name>targetFilterLifecycle</param-name><param-value>true</param-value></init-param></filter><filter-mapping><filter-name>shiroFilter</filter-name><url-pattern>/*</url-pattern></filter-mapping>

3、使用mybatis逆向生成工具生成我们所需要的表的model和mapper

  <table schema="" tableName="t_shiro_user" domainObjectName="User"enableCountByExample="false" enableDeleteByExample="false"enableSelectByExample="false" enableUpdateByExample="false"></table><table schema="" tableName="t_shiro_role" domainObjectName="RoUserle"enableCountByExample="false" enableDeleteByExample="false"enableSelectByExample="false" enableUpdateByExample="false"></table><table schema="" tableName="t_shiro_user_role" domainObjectName="Role"enableCountByExample="false" enableDeleteByExample="false"enableSelectByExample="false" enableUpdateByExample="false"></table><table schema="" tableName="t_shiro_permission" domainObjectName="Permission"enableCountByExample="false" enableDeleteByExample="false"enableSelectByExample="false" enableUpdateByExample="false"></table><table schema="" tableName="t_shiro_role_permission" domainObjectName="RoPermission"enableCountByExample="false" enableDeleteByExample="false"enableSelectByExample="false" enableUpdateByExample="false"></table>

4、在userMapper.xml中映射根据用户名查找的方法

由于我们使用md5将密码加密后,我们用户在登陆时就不需要向以前一样拿到用户密码,而是使用用户名进行查找

 <select id="queryUserByUserName" resultType="com.zjy.model.User" parameterType="java.lang.String">select<include refid="Base_Column_List" />from t_shiro_userwhere userName = #{userName}</select>

5、在mapper与业务层中添加方法

mapper

 User queryUserByUserName(@Param("user") String userName);

userbiz

package com.zjy.biz;import com.zjy.model.User;
import org.apache.ibatis.annotations.Param;/*** @author zjy* @site Bi8boYin* @company xxx公司* @create  2022-08-25 13:55*/
public interface UserBiz {int updateByPrimaryKey(User record);int deleteByPrimaryKey(Integer userid);int insert(User record);int insertSelective(User record);User selectByPrimaryKey(Integer userid);User queryUserByUserName(@Param("user") String userName);int updateByPrimaryKeySelective(User record);
}

业务实现类:当我们将数据交给shiro时,spring的上下文还未加载完毕,所以需要我们将业务层添加进类注解中

package com.zjy.biz.impl;import com.zjy.biz.UserBiz;
import com.zjy.mapper.UserMapper;
import com.zjy.model.User;
import org.springframework.stereotype.Service;/*** @author zjy* @site Bi8boYin* @company xxx公司* @create  2022-08-25 14:00*/
@Service("UserBiz")
public class UserBizImpl implements UserBiz {private UserMapper userMapper;@Overridepublic int updateByPrimaryKey(User record) {return userMapper.updateByPrimaryKey(record);}@Overridepublic int deleteByPrimaryKey(Integer userid) {return userMapper.deleteByPrimaryKey(userid);}@Overridepublic int insert(User record) {return userMapper.insert(record);}@Overridepublic int insertSelective(User record) {return userMapper.insertSelective(record);}@Overridepublic User selectByPrimaryKey(Integer userid) {return userMapper.selectByPrimaryKey(userid);}@Overridepublic User queryUserByUserName(String userName) {return userMapper.queryUserByUserName(userName);}@Overridepublic int updateByPrimaryKeySelective(User record) {return userMapper.updateByPrimaryKeySelective(record);}
}

6、自定义域 Myrealm继承域

package com.zjy.shiro;import com.zjy.biz.UserBiz;
import com.zjy.model.User;
import sun.net.www.protocol.http.AuthenticationInfo;/*** @author zjy* @site Bi8boYin* @company xxx公司* @create  2022-08-25 14:12*/
public class MyRealm extends AuthorizingRealm {private UserBiz userBiz;public UserBiz getUserBiz() {return userBiz;}public void setUserBiz(UserBiz userBiz) {this.userBiz = userBiz;}@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {System.out.println("身份认证...");String username = token.getPrincipal().toString();String password = token.getCredentials().toString();User user = userBiz.queryUserByUserName(username);
//        拿到数据库中的用户信息,放入token凭证中,用于controler进行对比AuthenticationInfo info = new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),ByteSource.Util.bytes(user.getSalt()),this.getName());return info;}
}

7、配置spring与shiro的集成文件

<?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"><!--配置自定义的Realm--><bean id="shiroRealm" class="com.zjy.shiro.MyRealm"><property name="UserBiz" ref="UserBiz" /><!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 --><!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 --><!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 --><!--以下三个配置告诉shiro将如何对用户传来的明文密码进行加密--><property name="credentialsMatcher"><bean id="credentialsMatcher" class="org.apache.shiro.authc.credential.HashedCredentialsMatcher"><!--指定hash算法为MD5--><property name="hashAlgorithmName" value="md5"/><!--指定散列次数为1024次--><property name="hashIterations" value="1024"/><!--true指定Hash散列值使用Hex加密存. false表明hash散列值用用Base64-encoded存储--><property name="storedCredentialsHexEncoded" value="true"/></bean></property></bean><!--注册安全管理器--><bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"><property name="realm" ref="shiroRealm" /></bean><!--Shiro核心过滤器--><bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean"><!-- Shiro的核心安全接口,这个属性是必须的 --><property name="securityManager" ref="securityManager" /><!-- 身份验证失败,跳转到登录页面 --><property name="loginUrl" value="/login"/><!-- 身份验证成功,跳转到指定页面 --><!--<property name="successUrl" value="/index.jsp"/>--><!-- 权限验证失败,跳转到指定页面 --><property name="unauthorizedUrl" value="/unauthorized.jsp"/><!-- Shiro连接约束配置,即过滤链的定义 --><property name="filterChainDefinitions"><value><!--注:anon,authcBasic,auchc,user是认证过滤器perms,roles,ssl,rest,port是授权过滤器--><!--anon 表示匿名访问,不需要认证以及授权--><!--authc表示需要认证 没有进行身份认证是不能进行访问的--><!--roles[admin]表示角色认证,必须是拥有admin角色的用户才行-->/user/login=anon/user/updatePwd.jsp=authc/admin/*.jsp=roles[admin]/user/teacher.jsp=perms["user:update"]<!-- /css/**               = anon/images/**            = anon/js/**                = anon/                     = anon/user/logout          = logout/user/**              = anon/userInfo/**          = authc/dict/**              = authc/console/**           = roles[admin]/**                   = anon--></value></property></bean><!-- Shiro生命周期,保证实现了Shiro内部lifecycle函数的bean执行 --><bean id="lifecycleBeanPostProcessor" class="org.apache.shiro.spring.LifecycleBeanPostProcessor"/>
</beans>

8、编写登陆的控制层代码

package com.zjy.controller;import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.subject.Subject;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
@Controller
public class LoginController {@RequestMapping("/login")public String login(HttpServletRequest req, HttpServletResponse resp){String username = req.getParameter("username");String password = req.getParameter("password");UsernamePasswordToken usernamePasswordToken = new UsernamePasswordToken(username, password);Subject subject = SecurityUtils.getSubject();try {subject.login(usernamePasswordToken);req.getRequestDispatcher("main.jsp").forward(req, resp);} catch (Exception e) {req.setAttribute("message", "您的用户名密码输入有误!!!");try {req.getRequestDispatcher("login.jsp").forward(req, resp);} catch (ServletException e1) {e1.printStackTrace();} catch (IOException e1) {e1.printStackTrace();}}return null;}@RequestMapping("/logout")public String logout(HttpServletRequest req, HttpServletResponse resp){Subject subject = SecurityUtils.getSubject();subject.logout();try {resp.sendRedirect(req.getContextPath()+"/login.jsp");} catch (IOException e) {e.printStackTrace();}return null;}
}

二、密码加盐加密

盐加密工具类,在做新增用户的时候使用,将加密后的密码、及加密时候的盐放入数据库;

package com.zjy.util;import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;public class PasswordHelper {/*** 随机数生成器*/private static RandomNumberGenerator randomNumberGenerator = new SecureRandomNumberGenerator();/*** 指定hash算法为MD5*/private static final String hashAlgorithmName = "md5";/*** 指定散列次数为1024次,即加密1024次*/private static final int hashIterations = 1024;/*** true指定Hash散列值使用Hex加密存. false表明hash散列值用用Base64-encoded存储*/private static final boolean storedCredentialsHexEncoded = true;/*** 获得加密用的盐** @return*/public static String createSalt() {return randomNumberGenerator.nextBytes().toHex();}/*** 获得加密后的凭证** @param credentials 凭证(即密码)* @param salt        盐* @return*/public static String createCredentials(String credentials, String salt) {SimpleHash simpleHash = new SimpleHash(hashAlgorithmName, credentials,salt, hashIterations);return storedCredentialsHexEncoded ? simpleHash.toHex() : simpleHash.toBase64();}/*** 进行密码验证** @param credentials        未加密的密码* @param salt               盐* @param encryptCredentials 加密后的密码* @return*/public static boolean checkCredentials(String credentials, String salt, String encryptCredentials) {return encryptCredentials.equals(createCredentials(credentials, salt));}public static void main(String[] args) {//盐String salt = createSalt();System.out.println(salt);System.out.println(salt.length());//凭证+盐加密后得到的密码String credentials = createCredentials("123", salt);System.out.println(credentials);System.out.println(credentials.length());boolean b = checkCredentials("123", salt, credentials);System.out.println(b);}
}

测试结果:

盐加密的运行结果:

注意看两次密码都是一样的,但是最后加密出来的结果是不一样的:这就体现了Shiro框架的安全性高

接下来看看md5加密后的结果:

加密密码123456:

当我再次打开网站时,(注意时间)去加密这个密码时,加密结果还是一样的:

经过以上对比,md5的加密方式和Shiro的盐加密,shiro的盐加密安全性更高!

补充:

1、简介:MD5消息摘要算法,属Hash算法一类。MD5算法对输入任意长度的消息进行运行,产生一个128位的消息摘要(32位的数字字母混合码)。

2、MD5主要特点:不可逆,相同数据的MD5值肯定一样,不同数据的MD5值不一样

3、MD5的性质:3.1、压缩性3.2、容易计算3.3、抗修改性3.4、弱抗碰撞3.5、强抗碰撞

Shiro认证及加盐加密相关推荐

  1. 【Shiro权限管理】10.Shiro为密码加盐

    上一篇我们提到了使用Shiro为密码进行MD5加密,这次来说一下密码加盐的问题. 当两个用户的密码相同时,单纯使用不加盐的MD5加密方式,会发现数据库中存在相同结构的密码, 这样也是不安全的.我们希望 ...

  2. Python项目-Day26-数据加密-hash加盐加密-token-jwt

    Python项目-Day26-数据加密-hash加盐加密-token-jwt 数据加密 import hashlibpwd='a123456' #sha1的参数必须是二进制 temp=hashlib. ...

  3. 【SpringSSM项目】搏击俱乐部 使用邮箱进行登录注册 密码加盐加密

    在注册页面使用邮箱进行注册,注册后发送带有确认码的邮件到邮箱中,通过邮件确认注册 编写数据库 登录注册需要使用到用户表 table userinfo 包含 账号状态 用户名 邮箱 密码 头像 过期时间 ...

  4. 基于java注册登录MD5算法加盐加密颁发 Token身份令牌使用各种邮箱发送验证码详解雪花算法

    目的作用 == 在项目中,为了防止别人窥视我们的密码通常我们会采取一些加密方式.这里简单介绍一下MD5 加盐加密方法,MD5叫做信息-摘要算法,严格来说不是加密方式,而是信息摘要. 对于可以接触到数据 ...

  5. MD5工具类 加盐加密 及编码

    titls: MD5工具类加密 date: 2018/11/12 10:03:42 categories: 开发module import java.security.MessageDigest; i ...

  6. md5加密,md5加盐加密和解密

    package com.java.test;import java.security.MessageDigest; import java.security.SecureRandom; import ...

  7. 密码MD5加盐加密----注册、校验、修改模块

    思路:     单纯的MD5加密容易被碰撞破解,考虑将密码加上一个随机字符串(盐),再一同进行MD5加密,提高安全性. 此时,盐相当于另一半秘钥,需将盐一同存入数据库,用以验证. 实现过程:      ...

  8. MD5加盐加密工具类(可直接使用)

    MD5加盐加密工具类 在我们做项目时,涉及到用户密码,而正常来说数据库中不会直接存储明文的密码,都是加密之后的密码. 密码加密的方式有很多,比如: ① 3DES.AES.DES:使用对称加密算法,可以 ...

  9. java md5加盐与解密_md5加密,md5加盐加密和解密

    packagecom.java.test;importjava.security.MessageDigest;importjava.security.SecureRandom;importjava.u ...

最新文章

  1. Android AdapterView 源码分析以及其相关回收机制的分析
  2. 添加Graphic Drivers PPA
  3. 你了解 Assembly.Load 吗?
  4. 手写springiocxml方式注入对象
  5. linux板级初始化
  6. 关于关闭Eclipse的控制台自动跳出
  7. BJ-100型矩形波导传输TE10模,测得波导中相邻两个电场波节点之间的距离为19.88mm
  8. css中的.clearfix是什么意思?
  9. 网络安全学习中的工具
  10. photoshop cs6 界面字体太小解决方法
  11. Android新浪微博分页加载,使用LoadMoreWrapper为RecyclerView实现分页加载
  12. 【机器学习】——逻辑模型:树模型(决策树)
  13. mysql list dbs_关于mysql_list_dbs()函数的10篇文章推荐
  14. mendix费用价格
  15. linux查看指定目录下各个文件大小以及总体大小
  16. 连续微小线段速度前瞻规划算法
  17. 物联网应用技术和计算机应用技术哪个更好,物联网应用技术和计算机应用技术的优劣?...
  18. 关于PWA的各种问题
  19. opencv亚像素边缘精度_opencv亚像素边缘检测
  20. 课程名称:用AI做毛绒质感小毛球-CSDN就业班-专题视频课程

热门文章

  1. WebRTC音视频数据采集 六、第一节 WebRTC音视频数据采集
  2. 华为OD软件工程师面试总结
  3. 华硕p6t7支持服务器cpu吗,宇宙最强X58 华硕P6T7WS工作站主板评测
  4. 【2阶】BootStrap制作简易CRM管理系统-crm-1
  5. Android 文本比较 APP,一个android文本比对APP的实现(三)-设计模式在文件选择模块中的运用...
  6. ucl计算机教授汪军,UCL汪军教授:多智能体机器学习
  7. 掌握坐标轴的log转换
  8. 北上广测试工程师月薪20K往上,该如何做,需要会什么技能?
  9. OB0205 obsidian 主题修改插件:Style Settings插件使用
  10. C-L学习打卡(7.6)