Shiro认证-身份认证加密
目录
一、盐加密
什么是盐加密?
数据库密码的发展史
1.1pom依赖
1.2web.xml配置
1.3密码工具类
测试
盐加密新增用户的操作流程:
二、shiro认证
步骤
1.通过逆向工程将五张表生成对应的model、编辑
2.中新增
整合
配置文件-shiro.xml
完成自定义realm
层
测试
一、盐加密 什么是盐加密?
在面对这个网络世界的时候,密码安全总是各个公司和用户都非常关心的一个内容,毕竟现在大家不管是休闲娱乐还是学习购物都是通过网上的帐号来进行消费的,所以我们通常会给用户的密码进行加密。在加密的时候,经常会听到“加盐”这个词,这是什么意思呢?
加盐加密是一种对系统登录口令的加密方式,它实现的方式是将每一个口令同一个叫做”盐“(salt)的n位随机数相关联。无论何时只要口令改变,随机数就改变。随机数以未加密的方式存放在口令文件中,这样每个人都可以读。不再只保存加密过的口令,而是先将口令和随机数连接起来然后一同加密,加密后的结果放在口令文件中。
定义:将每一个口令同“盐”随机关联
数据库密码的发展史
第一个阶段:明文密码
第二个阶段:MD5加密 如:
第三个阶段:MD5加盐加密
第四个阶段:MD5加盐加密加次数
由于明文密码泄露出去后很容易会造成不好的影响,没有保密性,所以就有了之后的各种加密方式 本篇我们将使用的是md5加盐加密加次数的加密方式
1.1pom依赖
org.apache.shiro shiro-core 1.3.2
org.apache.shiro shiro-web 1.3.2
org.apache.shiro shiro-spring 1.3.2
1.2web.xml配置
shiroFilter org.springframework.web.filter.DelegatingFilterProxy targetFilterLifecycle true
shiroFilter /*
1.3密码工具类
package com.oyang.shiro;import org.apache.shiro.crypto.RandomNumberGenerator;
import org.apache.shiro.crypto.SecureRandomNumberGenerator;
import org.apache.shiro.crypto.hash.SimpleHash;/*** 用于shiro权限认证的密码工具类*/
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("123456", salt);System.out.println(credentials);System.out.println(credentials.length());boolean b = checkCredentials("123456", salt, credentials);System.out.println(b);}
}
测试
盐加密新增用户的操作流程:
form
用户:oyang
密码:
传到后台
1.生成随机的盐
2.利用 原始密码 + 生成随机的盐 得到加密后的密码
3.
二、shiro认证 步骤
1)完成登录的方法 层的编写,接着biz层
2)完成自定义realm(重点)
3)与Shiro的整合(注意)
3.1)shiro在加载的时候,上下文还没有加载完毕
所以@与@是不能使用
3.2)-shiro.xml文件中,需要依赖的业务
由于没有被配置,所以需要指定的bean的id
通过@("具体的名字")
4)测试
1.通过逆向工程将五张表生成对应的model、
.xml
2.中新增
Biz层
package com.oyang.ssm.biz;import com.oyang.ssm.model.User;
import org.apache.ibatis.annotations.Param;public interface UserBiz {int deleteByPrimaryKey(Integer userid);int insert(User record);int insertSelective(User record);User selectByPrimaryKey(Integer userid);User queryUserByUserName(String username);int updateByPrimaryKeySelective(User record);int updateByPrimaryKey(User record);
}
实现类
package com.oyang.ssm.impl;import com.oyang.ssm.biz.UserBiz;
import com.oyang.ssm.mapper.UserMapper;
import com.oyang.ssm.model.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/*** @author oyang* @site https://blog.csdn.net* @qq 1828190940* @create 2022-08-25 19:59*/
@Service("userBiz")
public class UserBizImpl implements UserBiz {@Autowiredprivate UserMapper userMapper;@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);}@Overridepublic int updateByPrimaryKey(User record) {return userMapper.updateByPrimaryKey(record);}
}
整合 配置文件-shiro.xml
/user/login=anon/user/updatePwd.jsp=authc/admin/*.jsp=roles[admin]/user/teacher.jsp=perms["user:update"]
将此段加入到.xml配置文件中
完成自定义realm
package com.oyang.ssm.shiro;import com.oyang.ssm.biz.UserBiz;
import com.oyang.ssm.model.User;
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.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.util.ByteSource;/*** @author oyang* @site https://blog.csdn.net* @qq 1828190940* @create 2022-08-25 20:07*/
public class MyRealm extends AuthorizingRealm {public UserBiz getUserBiz(){return userBiz;
}public void setUserBiz(UserBiz userBiz){this.userBiz=userBiz;
}public UserBiz userBiz;/*** 授权* @param principals* @return* 替代了shiro-web.ini*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {return null;}/*** 认证* @param token* @return* @throws AuthenticationException* 替代了*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {String userName = token.getPrincipal().toString();User user = userBiz.queryUserByUserName(userName);AuthenticationInfo info=new SimpleAuthenticationInfo(user.getUsername(),user.getPassword(),ByteSource.Util.bytes(user.getSalt()),this.getName()//Realm的名字);return info;}
}
层
package com.oyang.ssm.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.http.HttpServletRequest;/*** @author oyang* @site https://blog.csdn.net* @qq 1828190940* @create 2022-08-19 16:35*/
@Controller
public class LoginController {/* //登录@RequestMapping("/login")public String login(HttpServletRequest request){//登录成功 需要保存用户登陆信息String uname = request.getParameter("uname");if("oyang".equals(uname)){//数据定死了,如果用户名是oyang就代表登录成功//登录成功就保存到session里去request.getSession().setAttribute("uname",uname);}return "index";}*//* //登出@RequestMapping("/logout")public String logout(HttpServletRequest request){//销毁request.getSession().invalidate();return "index";}*///登录@RequestMapping("/login")public String login(HttpServletRequest request){try {String username = request.getParameter("username");String password = request.getParameter("password");UsernamePasswordToken token=new UsernamePasswordToken(username,password);Subject subject = SecurityUtils.getSubject();subject.login(token);return "main";}catch (Exception e){request.setAttribute("message","账号密码错误");return "login";}}//登出@RequestMapping("/logout")public String logout(HttpServletRequest request){Subject subject = SecurityUtils.getSubject();subject.logout();return "login";}
}
测试