SSH登陆模块

来源:互联网 发布:霸王别姬 知乎 蒋雯丽 编辑:程序博客网 时间:2024/06/06 06:18

利用Maven搭建的SSH实现带有验证码和密码加密方式的登陆功能。

搭建SSH

首先搭建SSH,可以参考利用Maven搭建SSM项目

配置实体类

利用注解配置User实体类,然后利用Hibernate生成相应的数据表。注意要在Hibernate配置文件中配置实体类的位置和表的生成策略。

@Entity@Table(name = "user")public class User {    @Id    @GeneratedValue(strategy = GenerationType.IDENTITY)    private Long user_id;    @Column    private String user_code;    @Column    private String user_name;    @Column    private String user_password;    @Column    private Character user_state;    public String getUser_code() {    return user_code;    }    public void setUser_code(String user_code) {    this.user_code = user_code;    }    public String getUser_name() {    return user_name;    }    public void setUser_name(String user_name) {    this.user_name = user_name;    }    public String getUser_password() {    return user_password;    }    public Long getUser_id() {    return user_id;    }    public void setUser_id(Long user_id) {    this.user_id = user_id;    }    public void setUser_password(String user_password) {    this.user_password = user_password;    }    public Character getUser_state() {    return user_state;    }    public void setUser_state(Character user_state) {    this.user_state = user_state;    }}

前端展示页面

一个带有基本功能的展示页面,用Ajax的post方式提交表单数据,如果状态码等于200的话登陆成功,否则登陆失败,打印出登陆失败的信息并刷新验证码。

<%@ page language="java" contentType="text/html; charset=UTF-8"    pageEncoding="UTF-8"%><!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>登陆界面</title><script src="http://libs.baidu.com/jquery/2.0.0/jquery.js"></script></head><body>    <h3>用户登陆</h3>    <form action="LoginAction_login.do" id="form1" method="post">        <table>            <tr>                <td><label for="username">用户名:</label></td>                <td><input type="text" name="userName" id="username" /></td>            </tr>            <tr>                <td><label for="password">密码:</label></td>                <td><input type="password" name="password" id="password" /></td>            </tr>            <tr>                <td><label for="verify">验证码:</label></td>                <td><input type="text" name="verify" id="verify" /></td>            </tr>            <tr>                <td></td>                <td><img src="getVerifyAction.do" id="imgCode" /></td>            </tr>            <tr>                <td></td>                <td><input type="submit" /></td>            </tr>            </form>        </table></body><script type="text/javascript">    $(function() {        $("#imgCode").click(function() {            refreshCode();        });        $("#form1").submit(                function() {                    $.post("LoginAction_login.do", $("#form1").serialize(),                            function(data) {                                if (data.state == 200) {                                    //跳转界面                                    alert("success");                                } else {                                    alert(data.msg);                                    refreshCode();                                }                            })                    return false;                })    })    //刷新验证码    function refreshCode() {        var url = "getVerifyAction.do?" + new Date().getTime(); //加时间戳防止缓存          $("#imgCode").attr("src", url);    }</script></html>

后端逻辑

首先是dao层,同过service层传入的用户名判断是否存在该用户,没有则返回null

  public User findUserByName(String name) {    String sql = "from User where user_name = ?";    List<User> lists = (List<User>) getHibernateTemplate().find(sql, name);    if (lists.isEmpty()) {        return null;    }    return lists.get(0);    }

然后是service层,通过controller层传入的User 用户,然后通过判断是否存在该用户,没有则直接抛出异常。有则继续判断密码加密后是否相同。

  public void login(User u) {    // TODO Auto-generated method stub    User u1 = dao.findUserByName(u.getUser_name());    if (u1 == null) {        throw new RuntimeException("用户民不存在");    }    if (!u1.getUser_password().equals(MD5Utils.md5(u.getUser_password()))) {        throw new RuntimeException("密码错误");    }    }

生成随机的数字,然后把随机数让入session中,输出到页面。注意验证码是一个独立的Action,直接在img标签的src属性中写入验证码的Action,就会生成验证码图片。或者直接在浏览器输入验证码的Action,就会出现验证码的图片。

  @Controller("getVerifyAction")@Scope("prototype")public class GetVerifyAction {    /**     * 设置验证码     *      * @return     * @throws IOException     * @date 2017年10月15日 上午9:41:38     */    public String getVerifyImpage() throws IOException {    HttpServletResponse response = ServletActionContext.getResponse();    HttpServletRequest request = ServletActionContext.getRequest();    response.setContentType("image/jpeg");    response.setHeader("Pragma", "No-cache");    response.setHeader("Cache-Control", "no-cache");    response.setDateHeader("Expires", 0);    HttpSession session = request.getSession();    session.removeAttribute("verifyCode");    int width = 70, height = 23;    BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);    // 获取图形上下文    Graphics g = image.getGraphics();    // 生成随机类    Random random = new Random();    // 设定背景色    g.setColor(getRandColor(200, 250));    g.fillRect(0, 0, width, height);    // 设定字体    g.setFont(new Font("Times New Roman", Font.PLAIN, 20));    // 画边框    g.setColor(getRandColor(160, 200));    g.drawRect(0, 0, width - 1, height - 1);    // 随机产生100条干扰线    g.setColor(getRandColor(160, 200));    for (int i = 0; i < 100; i++) {        int x = random.nextInt(width);        int y = random.nextInt(height);        int xl = random.nextInt(10);        int yl = random.nextInt(10);        g.drawLine(x, y, x + xl, y + yl);    }    // 取随机产生4位数字    String sRand = "";    for (int i = 0; i < 4; i++) {        String rand = String.valueOf(random.nextInt(10));        sRand += rand;        g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));        g.drawString(rand, 13 * i + 14, 20);    }    // 将认证码存入SESSION    session.setAttribute("verifyCode", sRand);    System.out.println("verifyCode:" + session.getAttribute("verifyCode"));    // 图象生效    g.dispose();    // 输出图象到页面    ImageIO.write(image, "JPEG", response.getOutputStream());    return null;    }    private Color getRandColor(int fc, int bc) {// 给定范围获得随机颜色    Random random = new Random();    if (fc > 255)        fc = 255;    if (bc > 255)        bc = 255;    int r = fc + random.nextInt(bc - fc);    int g = fc + random.nextInt(bc - fc);    int b = fc + random.nextInt(bc - fc);    return new Color(r, g, b);    }}

登陆的Action,首先判断前端传入的验证码是否和session中的验证相等。
相等则把前台传入的账号,密码封装到User实体中,传入到service中。当然也可以不封装,直接把用户名,密码传入service,前台参数少可以这么做。如果前台传入的参数很多的话,最好封装到相对应的实体类中,一方面是更能体现出相对对象的写法,另一方面是写出的代码更加利于维护和简洁。
调用完service层方法后,如果没有抛出异常,则说明用户名和密码匹配。如果不匹配,就会抛出相应的异常,并且捕捉到Map集合中。

public class LoginAction extends ActionSupport {    @Autowired    LoginService service;    /**     * 登陆     *      * @return     * @throws IOException     * @date 2017年10月15日 下午5:42:47     */    public String login() throws IOException {    Map m = new HashMap();    boolean falg = ResultUtils.checkVerifyCode(verify);    if (falg) {        User u = new User();        u.setUser_name(userName);        u.setUser_password(password);        try {        service.login(u);        m.put("state", Result.SUCCESS.getState());        } catch (Exception e) {        // TODO: handle exception        String message = e.getMessage();        m.put("state", Result.ERROR.getState());        m.put("msg", message);        }    } else {        m.put("state", Result.ERROR.getState());        m.put("msg", "验证码错误");    }    //把Map集合转化为Json数据    ResultUtils.toJson(ServletActionContext.getResponse(), m);    return null;    }    private String userName;    private String password;    private Map<String, Object> jsonResult;    private String verify;    public String getVerify() {    return verify;    }    public void setVerify(String verify) {    this.verify = verify;    }    public Map<String, Object> getJsonResult() {    return jsonResult;    }    public void setJsonResult(Map<String, Object> jsonResult) {    this.jsonResult = jsonResult;    }    public String getUserName() {    return userName;    }    public void setUserName(String userName) {    this.userName = userName;    }    public String getPassword() {    return password;    }    public void setPassword(String password) {    this.password = password;    }}

枚举类型的结果集,创建通过整形初始化和字符串和整形初始化的构造器。比如当调用Result.SUCCESS(200),可以初始化一个state为200的对象。然后Result.SUCCESS(200).getState()就可以获取该参数。

public enum Result {    SUCCESS(200), ERROR(400), INFO("请求超时", 100);    private String msg;    private int state;    private Result(int state) {    this.state = state;    }    private Result(String msg, int state) {    this.msg = msg;    this.state = state;    }    public String getMsg() {    return msg;    }    public void setMsg(String msg) {    this.msg = msg;    }    public int getState() {    return state;    }    public void setState(int state) {    this.state = state;    }}

MD5加密的工具类,传入相应的密码就会获取该密码的加密的字符串。

public class MD5Utils {    /**     * 使用md5的算法进行加密     */    public static String md5(String plainText) {    byte[] secretBytes = null;    try {        secretBytes = MessageDigest.getInstance("md5").digest(plainText.getBytes());    } catch (NoSuchAlgorithmException e) {        throw new RuntimeException("没有md5这个算法!");    }    String md5code = new BigInteger(1, secretBytes).toString(16);// 16进制数字    // 如果生成数字未满32位,需要前面补0    for (int i = 0; i < 32 - md5code.length(); i++) {        md5code = "0" + md5code;    }    return md5code;    }    public static void main(String[] args) {    System.out.println(md5("1234"));    }}

由于把对象转化为Json数据和检查验证码是否相等,在许多地方都能够用到,因此把大量重复的代码提取出来,制作成工具类。更加使代码简洁,优雅,也更能体现面对对象的思想。

public class ResultUtils {    /**     * 转化json数据     *      * @date 2017年10月15日 下午4:03:29     */    public static void toJson(HttpServletResponse response, Object data) throws IOException {    Gson gson = new Gson();    String result = gson.toJson(data);    response.setContentType("text/json; charset=utf-8");    response.setHeader("Cache-Control", "no-cache"); // 取消浏览器缓存    PrintWriter out = response.getWriter();    out.print(result);    out.flush();    out.close();    }    /**     * 验证验证码是否相等     *      * @param originVerifyCode     * @return     * @date 2017年10月15日 上午9:47:30     */    public static boolean checkVerifyCode(String originVerifyCode) {    HttpServletRequest request = ServletActionContext.getRequest();    HttpSession session = request.getSession();    String verifyCode = (String) session.getAttribute("verifyCode");    if (originVerifyCode.equals(verifyCode)) {        return true;    }    return false;    }}

展示效果

成功

这里写图片描述

密码错误

这里写图片描述

用户名不存在

这里写图片描述

原创粉丝点击