使用MD5加密的登陆demo

来源:互联网 发布:js object to date 编辑:程序博客网 时间:2024/05/17 04:11
最近接手了之前的一个项目,在看里面登陆模块的时候,遇到了一堆问题。现在记录下来。
这个登陆模块的逻辑是这样的
1 首先在登陆之前,调用后台的UserLoginAction类的getRandomKey方法产生一个随机字符串。
2 在前台获得用户名的登陆密码后,首先是要md5对其加密,之后把加密的结果与之前的随机字符串合并,使用md5再次加密,并把最后的结果作为用户的密码传给后台。
3 后台获得前台的用户名后(用户名全局唯一),先找出这个用户的密码(数据库里的真实密码),先用md5加密,再与第一步产生的随机字符串合并,之后使用md5二次加密
4 比照第三步产生的密码与从前台获得的密码。如果相等,说明登陆成功。
OK,我们看代码
起始页面:
//index.jsp<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%>    <%@ taglib prefix="s" uri="/struts-tags"%>    <s:action name="index" namespace="/" executeResult="true" var="rd"/><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body></body></html>
index.jsp里面只有一个action请求。
看看struts.xml的配置情况
<?xml version="1.0" encoding="UTF-8" ?><!DOCTYPE struts PUBLIC    "-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"    "http://struts.apache.org/dtds/struts-2.0.dtd"><struts>    <package name="core" namespace="/" extends="struts-default">                 <action name="index" class="userLoginAction"     method="getRandomKey">                 <result name="success">login.jsp</result>        </action>                <action name="login" class="userLoginAction" method="login">            <result name="success">main.jsp</result>            <result name="input">login.jsp</result>            <result name="error">login.jsp</result>        </action>        </package></struts>
我引入了Spirng来管理类。
看看UserLoginAction
注意要加上prototype
/** * @author dell * */@Component@Scope("prototype")public class UserLoginAction extends BaseAction{        /**     * 接收JSP传来的账号与密码     */    private Users user;    /**     * 随机字符串作为加密密钥     */    private String randomString;    /**     * 生成随机字符串作为密钥     */    public String getRandomKey() {        String base = "abcdefghijklmnopqrstuvwxyz0123456789";        Random random = new Random();        StringBuffer sb = new StringBuffer();        int length = 6;        for (int i = 0; i < length; i++) {            int number = random.nextInt(base.length());            sb.append(base.charAt(number));        }            //    logger.info("randomString: " + sb.toString());        this.randomString = sb.toString();        return SUCCESS;    }}
我们再看看返回的login.jsp
这个文件引入了MD5.js。
<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><%@ taglib prefix="s" uri="/struts-tags"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head>    <title>短波应急接入网管理系统</title>        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />        <meta http-equiv="pragma" content="no-cache" />        <meta http-equiv="cache-control" content="no-cache" />        <meta http-equiv="expires" content="0" />        <meta http-equiv="keywords" content="keyword1,keyword2,keyword3" />                <link rel="shortcut icon" href="logo.ico" type="image/x-icon" />        <link rel="stylesheet" type="text/css" href="css/common.css">                    <script type="text/javascript" src="easyui/jquery.min.js"></script>        <script type="text/javascript" src="easyui/jquery.easyui.min.js"></script>                <script type="text/javascript" src="js/md5.js"></script></head><body onload="document.getElementById('loginName').focus()"><div id="page">    <div class="t">                    <center>                        <span class="flderr">                             <s:fielderror>                                <s:param>error_msg</s:param>                             </s:fielderror> </span>                    </center>    </div>     <form action="login" id="login" method="post" class="ym_login_form" >        <div class="ymlf_row">            <span>用户编号:</span>            <input type="text" id="loginName" name="user.userName" class="ymlf_name" />        </div>        <div class="ymlf_row">            <span>用户密码:</span>                        <input type="password" id="loginPassword" name="user.passWord" class="ymlf_password" />            <input type="hidden" id="randomString"  name="randomString" value=<s:property value="randomString"/> />        //为什么要加上randomString?自己想一想        </div>        <div class="ymlf_btn_box">            <img src="images/bt1.png" class="sub"  onclick="mysubmit()" />                         <img src="images/bt2.png" class="res"  onclick="myreset()"  />        </div>    </form></div>    </body>        <script type="text/javascript">        function myreset(){             $('#login').form('clear');            }        function mysubmit(){             var frm = document.getElementById("login");            if(check(frm)==true)            frm.submit();        }        function check(frm) {            var lgnName = frm.loginName.value;            var lgnPassword = frm.loginPassword.value;            if(lgnName=='') {                $('.flderr').html("请输入用户名");                frm.loginName.focus();                return false;            }            if(lgnPassword=='') {                $('.flderr').html("请输入密码");                frm.loginPassword.focus();                return false;            }            var randomString = '<s:property value="randomString" />';            lgnPassword = hex_md5(lgnPassword);            lgnPassword = lgnPassword+randomString;            lgnPassword = hex_md5(lgnPassword);            $('#login').form('load',{                'user.passWord':lgnPassword            });                        return true;        }                document.onkeypress   =            function(event) {                var e = event||window.event;                var ele = e.target||e.srcElement;                var k = e.which||e.keyCode;                if(k == 13 && ele.id == 'loginPassword')                    mysubmit();        }</script></html>
提交的结果给了login那个aciton,最后调用的是UserLoginAction的login方法
         /**     * 用户登录处理     *     * @return "center_login" or "dept_login" or ERROR     */    @SuppressWarnings("unchecked")    public String login() {        if (user == null || user.getUserName() == null                || user.getPassWord() == null) {            return ERROR;        }        // 从客户端传来的加密后的密码        byte[] clientPassword = user.getPassWord().trim().getBytes();                        //逻辑就是这样 我自己写的dao就不给大家看了        //根据前台传过来的用户名从数据库取得用户                List<Users> resultList = (List<Users>) utilDAO.findListByProperty("Users", "userName",user.getUserName() ,"");        if (resultList.isEmpty()) { // 该账号不存在            this.addFieldError("error_msg", "该账号不存在");             logger.info("该账号不存在!!");            return ERROR;        } else {            user = resultList.get(0);            // 对用户真实的密码作同样的加密处理            String passwd = (String) user.getPassWord();            System.out.println("passwd  真实的:"+passwd);            MessageDigest md5 = null;            byte[] serverPassword = null;            try {                md5 = MessageDigest.getInstance("MD5");                md5.update(passwd.getBytes());                passwd = new BigInteger(1, md5.digest()).toString(16);                //md5(890617)后的之为09aaa5d27d99ad09a129a0734d52519b                //字符串以0开头,用BigInteger会把开头的0截去,导致位数减少,所以需要判断并补0                if (passwd.length() < 32) {                    for (int i = 0; i <32- passwd.length(); i++) {                        passwd = '0' + passwd;                    }                }                passwd = passwd + this.randomString;            //从前台通过s:hidden传来的randomString                System.out.println(randomString+"   aaaa"+"  "+this);                md5.update(passwd.getBytes());                serverPassword = (new BigInteger(1, md5.digest()).toString(16))                        .getBytes();                            } catch (NoSuchAlgorithmException e) {                e.printStackTrace();            }            if (!MessageDigest.isEqual(clientPassword, serverPassword)) {                this.addFieldError("error_msg", "用户名或密码错误");                logger.info("用户名或密码错误");                return ERROR;            }            this.getSession().put("user", user);            logger.info("登陆成功");            getLevel();            return SUCCESS;        }    }

在改写这个功能的时候,遇到很多问题。对就这么一个小小的登陆,实在是没有想到会碰到那么多问题。


问题1

<s:action name="index" namespace="/" executeResult="true" var="rd"/> 这是让后台产生随机字符串的action调用。
   如果把它放在login.jsp里,那么xml的配置文件里是否需要写result?
   如果不写result,在前台取不到randomString。这个很容易理解,你只是在login.jsp里调用这个action,login.jsp里凭什么能取到action里面的值呢?
   如果写result,按照下面的形式
                <action name="index" class="userLoginAction"     method="getRandomKey">
                 <result name="success">login.jsp</result>
        </action>
   会出现action与jsp调用的死循环。为什么?大家自己想。

   我没有办法,最后把让后台产生随机字符串的action调用放到了一个新的index.jsp里面,这个页面的唯一作用就是调用index这个action,返回的结果给login.jsp。

****************************************************

人蠢没办法。

前台直接获取调用action的值方法如下:

前台jsp调用action

//son1.jsp<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><%@ taglib prefix="s" uri="/struts-tags"%><s:action name="index1" namespace="/" executeResult="false" var="rd"/><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>Insert title here</title></head><body><%--  上面已经指定了acton的变量名为rd 这里直接用就是了 当然前面要加上#    --%><%--  另外atr1这个变量在下面的s:debug里是不存在的--%> <s:property value="#rd.atr1"/><s:debug></s:debug></body></html>


struts.xml   

<package name="testchain" namespace="/" extends="struts-default">           <action name="index1" class="chain.Action1">          </action>  </package>

public class Action1 extends ActionSupport {    /**     *     */    private static final long serialVersionUID = 4114388780011017030L;    private String atr1;    private String atr2;    public String execute() throws Exception {            System.out.println("set in action1");        atr1="dlf";               return SUCCESS;            }    //省略getset方法 }





问题2

 UserLoginAction应该是单例还是多例。

  从技术上来说,下面的就是多例
@Component
@Scope("prototype")
public class UserLoginAction extends BaseAction{
去掉 @Scope("prototype")之后就是单例。
如果是单例的话,用户名与密码在高并发下会发生覆盖问题。所以我们得采用多例。任何一个请求都对应唯一的一个action。

那么又出了一个新问题


问题3

 请求index这个action,后台产生了随机字符串,我们可以在login.jsp里访问随机字符串,但是

                <action name="login" class="userLoginAction" method="login">
            <result name="success">main.jsp</result>
            <result name="input">login.jsp</result>
            <result name="error">login.jsp</result>
        </action>    
这个action对应的对象是一个全新的对象,它的getRandomKey()方法还没有调用过。它里面的随机字符串还是空值呢。
最后的解决方法是给login.jsp上加上这行代码
<input type="hidden" id="randomString"  name="randomString" value=<s:property value="randomString"/> />
它是怎么解决问题的?自己想一想。
0 0
原创粉丝点击