一:先从登录开始,直接看代码

    @RequestMapping(value="dologin",method = {RequestMethod.GET, RequestMethod.POST},produces="text/html;charset=UTF-8")
@ResponseBody
public ResultJson systemUserdologin(XXX xxx,HttpServletRequest request,HttpServletResponse response, Model model) {
logger.info("=================dologin==============");
response.setHeader("Access-Control-Allow-Origin","*");//跨域
String msg=null ; Subject currentuser = SecurityUtils.getSubject();
CustomizedToken token = new CustomizedToken(user.getUsername(),user.getUserpassword(),ADMIN_LOGIN_TYPE);//设置多realm验证的type
try {
if(!currentuser.isAuthenticated()){ // 指明登录类型为管理员登录(在授权时使用)
currentuser.getSession().setAttribute("loginType", ADMIN_LOGIN_TYPE); //将管理员姓名保存到session中,方便在前台使用
currentuser.getSession().setAttribute("userName",xxx.getname()); token.setRememberMe(xxx.isRememberMe()); currentuser.login(token);//开始认证 if (currentuser.isAuthenticated()) {
logger.info("=================认证成功=============="); request.getSession().setAttribute("xxx",xxx); user.setUserstatus(2);//设置用户登录状态为已登录 SavedRequest savedRequest = WebUtils.getSavedRequest(request); // 获取保存的URL
if (savedRequest == null || savedRequest.getRequestUrl() == null) {
return new ResultJson(true, "身份认证成功,跳转到主页面", "");
} else {
return new ResultJson(true, "身份认证成功,跳转到主页面", "");
} } else {
logger.info("=================认证失败==============");
return new ResultJson(false, "身份认证失败,跳转到登录页面", "");
}
}else{
return new ResultJson(true, "已认证,跳转到主页面", "");
} } catch (IncorrectCredentialsException e) {
msg = "登录密码错误. Password for account " + token.getPrincipal() + " was incorrect.";
model.addAttribute("message", msg);
System.out.println(msg);
} catch (ExcessiveAttemptsException e) {
msg = "登录失败次数过多";
model.addAttribute("message", msg);
System.out.println(msg);
} catch (LockedAccountException e) {
msg = "帐号已被锁定. The account for username " + token.getPrincipal() + " was locked.";
model.addAttribute("message", msg);
System.out.println(msg);
} catch (DisabledAccountException e) {
msg = "帐号已被禁用. The account for username " + token.getPrincipal() + " was disabled.";
model.addAttribute("message", msg);
System.out.println(msg);
} catch (ExpiredCredentialsException e) {
msg = "帐号已过期. the account for username " + token.getPrincipal() + " was expired.";
model.addAttribute("message", msg);
System.out.println(msg);
} catch (UnknownAccountException e) {
msg = "帐号不存在. There is no user with username of " + token.getPrincipal();
model.addAttribute("message", msg);
System.out.println(msg);
} catch (UnauthorizedException e) {
msg = "您没有得到相应的授权!" + e.getMessage();
model.addAttribute("message", msg);
System.out.println(msg);
}
return new ResultJson(false, "身份认证失败,跳转到登录页面", "");
}

二、在realm中进行验证

    /**
* 首先执行这个登录验证,身份认证
* @param token
* @return
* @throws AuthenticationException
*/
@SuppressWarnings("unused")
@Override
protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
System.out.println("----->doGetAuthenticationInfo-->身份认证"+22222); //1.把AuthenticationToken转换为UsernamePasswordToken,token中储存着输入的用户名和密码 ,用户名用来确定账号是否存在,密码用来盐值加密
CustomizedToken userToken = (CustomizedToken) token; //2.获取系统管理员账号
String username = userToken.getUsername() ; //3.根据系统管理员账号获取系统管理员信息
SystemUser user = userMapper.findUserByUsername(username) ; System.out.println("user---------->"+user.toString()); //4.系统管理员存在则进行密码校验,否则,抛出异常:系统管理员不存在;
if (user!= null){ String roleName = userMapper.findRoles(username); //将前台需要的值放到session中去,方便使用
SecurityUtils.getSubject().getSession().setAttribute("roleName",roleName);
SecurityUtils.getSubject().getSession().setAttribute("id",user.getId()); System.out.println("从数据看中获取UserName为"+user.getUsername()+"所对应的信息。"); //1)principal:认证的实体信息,可以是username,也可以是数据库表对应的用户的实体对象
Object principal = user.getUsername(); //2)credentials:数据库中的密码
Object credentials = user.getUserpassword(); //3)realmName:当前realm对象的name,调用父类的getName()方法即可
String realmName = getName(); //4)credentialsSalt盐值
ByteSource credentialsSalt = ByteSource.Util.bytes(username);//使用账号作为盐值 //根据用户的情况,来构建AuthenticationInfo对象,通常使用的实现类为SimpleAuthenticationInfo
//5)与数据库中用户名和密码进行比对,密码盐值加密,第4个参数传入realName。
SimpleAuthenticationInfo info = new SimpleAuthenticationInfo(principal, credentials, credentialsSalt, realmName);
return info;
}else{
//6.若用户不存在,可以抛出UnknownAccountException
System.out.println("======不存在该用户=========>");
throw new UnknownAccountException("不存在该用户");//没找到帐号
}
}

三、以上便是登录和验证,但是问题是,shiro如何知道我们的密码时以什么方式加密的,加密了多少次呢?

具体配置如下:在配置realm的bean时,设置加密类型及加密的次数,这样shiro就知道了该如何对用户输入的密码进行验证,如果正确就验证通过,否则,验证失败

<!-- 注册自定义的Realm-->
<bean id="XXXRealm" class="com.shiro.XXXRealm">
<!-- 配置密码匹配器 -->
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!-- 加密算法为MD5 -->
<property name="hashAlgorithmName" value="MD5"></property>
<!-- 加密次数 -->
<property name="hashIterations" value="1024"></property>
</bean>
</property>
</bean> <bean id="YYYRealm" class="com.shiro.YYYRealm">
<!-- 配置密码匹配器 -->
<property name="credentialsMatcher">
<bean class="org.apache.shiro.authc.credential.HashedCredentialsMatcher">
<!-- 加密算法为MD5 -->
<property name="hashAlgorithmName" value="MD5"></property>
<!-- 加密次数 -->
<property name="hashIterations" value="1024"></property>
</bean>
</property>
</bean> <bean id="cacheManager" class="org.apache.shiro.cache.MemoryConstrainedCacheManager" /> <!-- 安全管理器 -->
<bean id="securityManager" class="org.apache.shiro.web.mgt.DefaultWebSecurityManager"> <property name="cacheManager" ref="cacheManager" /> <property name="authenticator" ref="authenticator"></property> <!-- 使用下面配置的缓存管理器 -->
<property name="sessionManager" ref="sessionManager" /> <!-- 可以配置多个Realm,其实会把realms属性赋值给ModularRealmAuthenticator的realms属性 -->
<property name="realms">
<list>
<ref bean="XXXRealm"/>
<ref bean="YYYRealm" />
</list>
</property>
</bean>

以上是登录的密码验证;

四、那注册加密如何实现呢?

首先一定要保证注册时的加密方式和上面的shiro的加密方式和加密的次数一致,否则注册成功也登陆不上去,这点一定要清楚!

    /******************************添加用户******************************************/
@RequestMapping("addUser")
@ResponseBody
public ResultJson addUser(XXX xxx,HttpServletRequest request){
System.out.println("======addUser=======");
System.out.println(xxx.toString());
//密码加密并set
user.setUserpassword(ShiroMd5Util.SysMd5(xxx));
ResultJson rj = new ResultJson();
boolean addUser_bl = userService.add(user);//将用户数据插入数据库
if (addUser_bl) {
rj.setSuccess(addUser_bl);
rj.setMsg("注册成功!");
}else{
rj.setSuccess(addUser_boolean);
rj.setMsg("注册失败!");
}
return rj;
}
public class ShiroMd5Util {
//添加user的密码加密方法
public static String SysMd5(XXX xxx) {
String hashAlgorithmName = "MD5";//加密方式 Object crdentials =xxx.getUserpassword();//密码原值 ByteSource salt = ByteSource.Util.bytes(xxx.getUsername());//以账号作为盐值 int hashIterations = 1024;//加密1024次 SimpleHash hash = new SimpleHash(hashAlgorithmName,crdentials,salt,hashIterations); return hash.toString();
}
}

注册时密码加密如上即可;

五、修改密码时如下:

    /******************************更新用户******************************************/
@RequestMapping("updateUser")
@ResponseBody
public ResultJson updateUser(XXX xxx,HttpServletRequest request){
System.out.println("======updateUser=======");
if(xxx.getId()==null){
return new ResultJson(false, "修改失败", "不存在该用户");
}//从数据哭获取的密码值
String dataBaseOldPassword = userService.selectSystemUserPassword(xxx.getId());
System.out.println("dataBaseOldPassword="+dataBaseOldPassword); //从页面传过来的旧密码值
String pageReturnOldPassword =ShiroMd5Util.UpdateSysMd5(xxx);//这个方法和上面的SysMd5一样,就是换了个马甲
System.out.println("pageReturnOldPassword="+pageReturnOldPassword); if(!dataBaseOldPassword.equals(pageReturnOldPassword)){
return new ResultJson(false, "修改失败", "旧密码不正确");
} //如果输入的旧密码和数据库一致,则将用户传进来的新密码覆盖旧密码,修改密码
user.setUserpassword(ShiroMd5Util.SysMd5(user)); ResultJson rj = new ResultJson(); //根据传进来的xxx的值是否存在更新数据
boolean upbl = userService.updateByPrimaryKeySelective(xxx); if(upbl){
rj.setSuccess(upbl);
rj.setMsg("修改成功");
rj.setObj("1");
}else{
rj.setSuccess(upbl);
rj.setMsg("修改失败");
rj.setObj("0");
}
return rj;
}

相关JSp页面代码如下,只粘贴关键代码:

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="shiro" uri="http://shiro.apache.org/tags"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script type="text/javascript" src="<%=basePath %>js/jquery-easyui-1.5.3/jquery.min.js"></script>
<script type="text/javascript" src="<%=basePath %>js/jquery-easyui-1.5.3/jquery.easyui.min.js"></script>
<script type="text/javascript" src="<%=basePath %>js/jquery-easyui-1.5.3/locale/easyui-lang-zh_CN.js"></script>
<link rel="stylesheet" type="text/css" href="<%=basePath %>js/jquery-easyui-1.5.3/themes/default/easyui.css"></link>
<link rel="stylesheet" type="text/css" href="<%=basePath %>js/jquery-easyui-1.5.3/themes/icon.css" ></link>
<link rel="stylesheet" type="text/css" href="<%=basePath %>js/jquery-easyui-1.5.3/themes/iconexp.css" ></link>
<link rel="stylesheet" href="<%=basePath %>font/font-awesome.min.css" type="text/css"></link>
<link rel="stylesheet" href="<%=basePath %>css/home.css" type="text/css"></link> <script type="text/javascript">
$(function(){
userForm = $('#userForm').form(); updatePasswordDialog = $('#updatePasswordDialog').show().dialog({
modal : true,
maximizable:true,
resizable:true,
width: 400,
title : '修改密码',
buttons : [
{
text : '确定',
handler : function() {
if (userForm.find('[name=id]').val()!='') {
userForm.form('submit', {
url : '<%=basePath%>UserManager/updateUser.do',
success : function(data) {
console.log(data);
var d = $.parseJSON(data);
if (d.success) {
updatePasswordDialog.dialog('close');
$.messager.show({
msg : '修改成功!',
title : '提示'
}); alert("修改成功,请到登录页面重新登录!"); //修改成功,重新登录
logout(true);
}
}
});
}else{
$.messager.show({
msg : '修改失败,请重新登录尝试修改!',
title : '提示'
});
}
}
},
{
text : '取消',
handler : function() {
updatePasswordDialog.dialog('close');
}
}
]
}).dialog('close'); }); function updatePassWord() {//打开增加部门领导的dialog的方法
updatePasswordDialog.dialog('open');
}
/*******************************************updatePassword-end****************************************************/ </script> </head>
<body class="easyui-layout" >
<div region="north" split="false" border="false" id="north" style="height: 100px; background: url('<%= request.getContextPath()%>/image/head-bg.jpg'); ">
<div style="float:right; height: 100px; width:70%;">
        ...........省略无关代码.............
<div >
<p class='icon' >
<shiro:hasRole name="super">
<a id="setIcon" style="visibility:hidden"><span onclick="settingNow()">设置</span></a>
</shiro:hasRole>
<a onclick="updatePassWord()"><span>修改密码</span></a>|
</p>
</div>
</script>
</div>
<div style="height:100px;padding-left:22px; width: 400px; ">
<img id="loginImg" src="<%= request.getContextPath()%>/image/companyLogo.png" width="65px" height="65px" style="margin-top: 20px;float: left;"/>
<p style="margin:12px 0 0 70px; padding-top: 25px; float: left;">
<span id="newUserName" style="font-size: 14px; margin-top: 10px; color:#f00 " ><%=session.getAttribute("userName")%>&nbsp;&nbsp;欢迎您!</span>
</p>
</div>
</div> <div id="updatePasswordDialog" style="display: none; overflow: hidden;">
<form id="userForm" method="post"> <input type="text" readonly="true" name="id" style="display: none; overflow: hidden;" value="<%=session.getAttribute("id")%>"/>
<input type="text" readonly="true" name="username" style="display: none; overflow: hidden;" value="<%=session.getAttribute("userName")%>"/> <table width="400" height="100" align="center" style="margin-top:20px">
<tr>
<td width="130" align="right" valign="middle">请输入旧密码:</td>
<td width="157" align="left" valign="middle">
<input type="password" name="olduserpassword" placeholder="输入旧密码">
</td>
</tr>
<tr>
<td align="right" valign="middle">请输入新密码:</td>
<td align="left" valign="middle">
<input type="password" name="userpassword" id="pwd1" placeholder="输入新密码">
</td>
</tr>
<tr>
<td align="right" valign="middle">请再次新密码:</td>
<td align="left" valign="middle">
<input type="password" name="againpassword" id="pwd2" placeholder="确认新密码">
</td>
</tr>
<tr>
<td align="right" valign="middle"></td>
<td align="left" valign="middle">
<span type="type" class="passwsordError" readonly="true" style="display: none; overflow: hidden;" val=""></span>
</td>
</tr> </table>
</form> </div> <script>
$(function(){
$("#pwd2").blur(function(){
var pwd1=$("#pwd1").val();
var pwd2=$(this).val();
if(pwd1!=pwd2){
$(".passwsordError").text("*两次密码输入不一致").css({"color":""});
$(".passwsordError").show();
}else{
$(".passwsordError").hide();
}
});
});
</script> </body>
</html>

end!

Shiro自定义realm实现密码验证及登录、密码加密注册、修改密码的验证的更多相关文章

  1. Django的内置登录、退出、修改密码方法

    Django中内置的登录.退出.修改密码方法. 1.url.py中使用django.contrib.auth中的views函数,django.views.generic中的TemplateView函数 ...

  2. Shiro自定义Realm时用注解的方式注入父类的credentialsMatcher

    用Shiro做登录权限控制时,密码加密是自定义的. 数据库的密码通过散列获取,如下,算法为:md5,盐为一个随机数字,散列迭代次数为3次,最终将salt与散列后的密码保存到数据库内,第二次登录时将登录 ...

  3. 权限框架 - shiro 自定义realm

    上篇文章中是使用的默认realm来实现的简单登录,这仅仅只是个demo,真正项目中使用肯定是需要连接数据库的 首先创建自定义realm文件,如下: 在shiro中注入自定义realm的完全限定类名: ...

  4. (3)shiro自定义realm

    上面一章说到shiro的认证和授权最底层就是调用realm的getAuthorizationInfo(获取用户的角色和资源)和getAuthenticationInfo(校验账号密码是否正确)两个方法 ...

  5. shiro自定义Realm

    1.1 自定义Realm 上边的程序使用的是shiro自带的IniRealm,IniRealm从ini配置文件中读取用户的信息,大部分情况下需要从系统的数据库中读取用户信息,所以需要自定义realm. ...

  6. shiro自定义realm支持MD5算法认证(六)

    1.1     散列算法 通常需要对密码 进行散列,常用的有md5.sha, 对md5密码,如果知道散列后的值可以通过穷举算法,得到md5密码对应的明文. 建议对md5进行散列时加salt(盐),进行 ...

  7. shiro自定义realm认证(五)

    上一节介绍了realm的作用: realm:需要根据token中的身份信息去查询数据库(入门程序使用ini配置文件),如果查到用户返回认证信息,如果查询不到返回null.token就相当于是对用户输入 ...

  8. Email接收验证码,以实现登录/注册/修改密码

    要求 1)实现Email形式的注册功能和相应的登录功能:2)实现忘记密码时的密码找回功能:3)存在数据库中的密码不能以明文形式存放,即建议在浏览器端发送请求前,调用js代码对用户的密码做md5加密 分 ...

  9. 用java语言写一个简易版本的登录页面,包含用户注册、用户登录、用户注销、修改密码等功能

    package com.Summer_0421.cn; import java.util.Arrays; import java.util.Scanner; /** * @author Summer ...

随机推荐

  1. Wireshark 的使用

    Wireshark 默认无法查看 https, 需要设置一下 新建环境变量 SSLKEYLOGFILE, 值为一个想要保存 sshKey 的文件, 如新建一个空文件 D:\AppData\SshKey ...

  2. idea录制宏

    录制一个热部署的快捷键 1.打开Edit-->Macros-->statr Macro Recording 打开之后idea右下角就会出现一个小圆点 然后就可以开始录制自己想要的快捷键 按 ...

  3. Kotlin 二分法算法游戏--猜价格

    本人最新想学习算法,算法是提高程序性能的关键! 程序就是数据结构和算法! 写了一个二分法的游戏,供大家参考: 当然,语言基于kotlin import java.util.* /** * Create ...

  4. anr trace文件分析

    测试给的trace文件好几万行,怎么看? 1.搜索 你的包名,看它报错误报在你代码的哪里 2.在你代码里面分析 还有,synchronized 就是用来防止多线程调用的,没有那么神奇.

  5. 开启虚拟机所报的错误:VMware Workstation cannot connect to the virtual machine. Make sure you have rights to run the program, access all directories the program uses, and access all directories for temporary fil

    当我们开启虚拟机时出现错误: VMware Workstation cannot connect to the virtual machine. Make sure you have rights t ...

  6. centos使用--开机启动

    centos6.8 1.利用 chkconfig 来配置启动级别 在CentOS或者RedHat其他系统下,如果是后面安装的服务,如httpd.mysqld.postfix等,安装后系统默认不会自动启 ...

  7. Apache Spark 2.2.0 中文文档

    Apache Spark 2.2.0 中文文档 - 快速入门 | ApacheCN Geekhoo 关注 2017.09.20 13:55* 字数 2062 阅读 13评论 0喜欢 1 快速入门 使用 ...

  8. java初学2

    1.数组操作类Arrays与System public static void arraycopy(Object src, int srcPos, Object dest,int destPos,in ...

  9. hnust 罚时计算器

    问题 F: 罚时计算器 时间限制: 1 Sec  内存限制: 128 MB提交: 229  解决: 63[提交][状态][讨论版] 题目描述 一般 ACM程序设计比赛都是五个小时.但是比赛结束时,DB ...

  10. django orderby

    https://www.douban.com/group/topic/44329052/