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

    @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. Android 内嵌 HTML5 并进行交互

    Android与HTML5的交互主要是两个部分, 与HTML5的交互以及与JavaScript的交互, 与HTML5的交互可以通过注册onclick事件转化为与JavaScript的交互 Androi ...

  2. python协程和IO多路复用

     协程介绍                                                                                                ...

  3. Win7更换锁屏和开机画面

    技术交流群:233513714 每次开机被Windows千年不变的开机画面和锁屏画面丑到的小伙伴们可以看过来,通过简单的几步就可以改掉系统默认的开机画面. 1.首先Windows+r键输入regedi ...

  4. 通俗版解释网关,IP地址,ARP欺骗,DDOS攻击

    计算机主机网关的作用是什么? 假设你的名字叫小不点,你住在一个大院子里,你的邻居有很多小伙伴,在门口传达室还有个看大门的李大爷,李大爷就是你的网关.当你想跟院子里的某个小伙伴玩,只要你在院子里大喊一声 ...

  5. erlang连接mysql [转]

    转自: http://blog.csdn.net/flyinmind/article/details/7740540 项目中用到erlang,同时也用到mysql.惯例,google. 但是,按照网上 ...

  6. 《数据结构与算法分析:C语言描述》复习——第四章“树”——二叉树

    2014.06.14 22:49 简介: 二叉树是学习树结构时接触的第一个概念,其他衍生的表示形式包括N叉树(随便多少叉).二叉链表(土话也叫左孩子右兄弟).由于单纯的二叉树是无序的,能做的事情不太多 ...

  7. Object Pascal中文手册 经典教程

    Object Pascal 参考手册 (Ver 0.1)ezdelphi@hotmail.com OverviewOverview(概述)Using object pascal(使用 object p ...

  8. Django笔记 —— 视图

    最近在学习Django,打算玩玩网页后台方面的东西,因为一直很好奇但却没怎么接触过.Django对我来说是一个全新的内容,思路想来也是全新的,或许并不能写得很明白,所以大家就凑合着看吧- 本篇笔记(其 ...

  9. 《数据结构》C++代码 邻接表与邻接矩阵

    上一篇“BFS与DFS”写完,突然意识到这个可能偏离了“数据结构”的主题,所以回来介绍一下图的存储:邻接表和邻接矩阵. 存图有两种方式,邻接矩阵严格说就是一个bool型的二维数组,map[i][j]表 ...

  10. 【Perceptron Learning Algorithm】林轩田机器学习基石

    直接跳过第一讲.从第二讲Perceptron开始,记录这一讲中几个印象深的点: 1. 之前自己的直觉一直对这种图理解的不好,老按照x.y去理解. a) 这种图的每个坐标代表的是features:fea ...