转载请标明出处:https://blog.csdn.net/men_ma/article/details/106847165.
本文出自 不怕报错 就怕不报错的小猿猿 的博客
shiro认证之md5加盐加密及shiro认证测试----SSM
- 目标
- 目录
- 1.shiro认证
-
- 第一步:导入pom.xml依赖
- 第二步:配置web.xml
- 第三步:通过逆向工程将五张表生成对应的model、mapper
- 第四步:写MyReaml.java文件(相当于ini文件),去调用数据库
- 第五步:shiro与spring整合
- 2.盐加密(MD5)
-
- 第一步:工具类PasswordHelper.java
- 3.shiro认证测试
-
- 第一步:MyRealm.java:
- 第二步:导入上一篇博客所用的jsp(代码 在上一篇博客有)
- 第三步:ShiroUserController.java(控制层)
- 第四步:测试看结果
目标
1、shiro认证
2、盐加密
目录
1.shiro认证
第一步:导入pom.xml依赖
<shiro.version>1.2.5</shiro.version><!-- shiro核心包 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-core</artifactId><version>${shiro.version}</version></dependency><!-- 添加shiro web支持 --><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-web</artifactId><version>${shiro.version}</version></dependency><dependency><groupId>org.apache.shiro</groupId><artifactId>shiro-spring</artifactId><version>${shiro.version}</version></dependency>
第二步:配置web.xml
<!-- 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>
第三步:通过逆向工程将五张表生成对应的model、mapper
Mapper中新增:
<select id="queryByName" resultType="com.xiaoqing.ssm.model.ShiroUser" parameterType="java.lang.String">select<include refid="Base_Column_List" />from t_shiro_userwhere username=#{uname}</select>
Service层ShiroUserService(接口类):
package com.xiaoqing.ssm.service;import com.xiaoqing.ssm.model.ShiroUser;
import org.apache.ibatis.annotations.Param;/*** @author 晴sister* @site https://blog.csdn.net/men_ma* @company* @create 2020-10-2819:11*/
public interface ShiroUserService {
ShiroUser queryByName(String uname);}
Service层ShiroUserServiceIpml.java(接口实现类):
package com.xiaoqing.ssm.service.impl;import com.xiaoqing.ssm.mapper.ShiroRoleMapper;
import com.xiaoqing.ssm.mapper.ShiroUserMapper;
import com.xiaoqing.ssm.model.ShiroUser;
import com.xiaoqing.ssm.service.ShiroUserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;/*** @author 晴sister* @site https://blog.csdn.net/men_ma* @company* @create 2020-10-2819:55*/
@Service("shiroUserService")
public class ShiroUserServiceImpl implements ShiroUserService {
@Autowiredprivate ShiroUserMapper shiroUserMapper;@Overridepublic ShiroUser queryByName(String uname) {
return shiroUserMapper.queryByName(uname);}
}
第四步:写MyReaml.java文件(相当于ini文件),去调用数据库
MyReaml.java:
在这里插入代码片
第五步:shiro与spring整合
applicationContext-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"xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"><!--配置自定义的Realm--><bean id="shiroRealm" class="com.xiaoqing.ssm.shiro.MyRealm"><property name="shiroUserService" ref="shiroUserService" /><!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 --><!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 --><!--注意:重要的事情说三次~~~~~~此处加密方式要与用户注册时的算法一致 --><!--以下三个配置告诉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>
在applicationContext.xml中添加:
<!--整合shiro--><import resource="applicationContext-shiro.xml"></import>
2.盐加密(MD5)
盐加密工具类,在做新增用户的时候使用,将加密后的密码、及加密时候的盐放入数据库;
本篇博客中的表数据是现成的,暂时用不上这个工具类去生成数据;
第一步:工具类PasswordHelper.java
package com.xiaoqing.ssm.utils;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);}
}
3.shiro认证测试
第一步:MyRealm.java:
package com.xiaoqing.ssm.shiro;import com.xiaoqing.ssm.model.ShiroUser;
import com.xiaoqing.ssm.service.ShiroUserService;
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;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;/*** @author 晴sister* @site https://blog.csdn.net/men_ma* @company* @create 2020-10-289:19*** 这个类替换掉了上堂课的ini文件,所有用户的身份都从这里来***** shiro入门七步走* * 1、将数据源realm读取到安全管理器securityManagerfactory* * 2、securityManagerfactory创建出安全管理器实例securityManager* * 3、将securityManager交给securityUtil** 前三步web.xml配置监听器已经帮你完成** * 4、securityUtil获取登录主体subject* * 5、从jsp获取到用户名密码然后将其组装成登录令牌token* * 6、subject去使用令牌token进行登录* * 7、登录可能成功,也可能失败,那么需要对登录的结果进行处理* **/
public class MyRealm extends AuthorizingRealm {
private ShiroUserService shiroUserService;public ShiroUserService getShiroUserService() {
return shiroUserService;}public void setShiroUserService(ShiroUserService shiroUserService) {
this.shiroUserService = shiroUserService;}/*** 授权的方法* @param principalCollection* @return*/@Overrideprotected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
return null;}/*** 身份认证的方法* @param authenticationToken* @return* @throws AuthenticationException*/@Overrideprotected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
// 获取身份(Principal)String uname=authenticationToken.getPrincipal().toString();
// 获取凭证/密码(Credentials)String pwd=authenticationToken.getCredentials().toString();
// 调用方法ShiroUser shiroUser = shiroUserService.queryByName(uname);/*** 第一个参数:principal(身份)* 第二个参数:hashedCredentials(凭证)* 第三个参数:credentialsSalt(凭证盐)* 第四个参数:realmName(realm的名字)*/AuthenticationInfo info =new SimpleAuthenticationInfo(shiroUser.getUsername(),shiroUser.getPassword(),ByteSource.Util.bytes(shiroUser.getSalt()),
// this代表类名,类对象的实例MyRealmthis.getName());return info;}
}
第二步:导入上一篇博客所用的jsp(代码 在上一篇博客有)
第三步:ShiroUserController.java(控制层)
package com.xiaoqing.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.HttpServlet;
import javax.servlet.http.HttpServletRequest;/*** @author 晴sister* @site https://blog.csdn.net/men_ma* @company* @create 2020-10-290:30*/
@Controller
public class ShiroUserController {
/*** 登录* @param req* @return*/@RequestMapping("/login")public String login(HttpServletRequest req){
Subject subject = SecurityUtils.getSubject();String uname=req.getParameter("username");String pwd=req.getParameter("password");UsernamePasswordToken token=new UsernamePasswordToken(uname,pwd);try {
// 这里会跳转到MyRealm中的认证方法subject.login(token);req.getSession().setAttribute("username",uname);return "main";}catch (Exception e){
req.setAttribute("message","用户名密码错误!!!!");return "login";}}/*** 退出* @param req* @return*/@RequestMapping("/logout")public String logout(HttpServletRequest req){
Subject subject = SecurityUtils.getSubject();subject.logout();return "redirect:/login.jsp";}
}
第四步:测试看结果