一步一步做项目(15)用户登录
在前面一步一步做项目(7)管理用户信息之Web页面构建的基础上进行,也就是你已经完成了基本的用户信息管理。
已经实现了用户信息的增删改查,能够保存到系统中,那么,如何进行用户登录呢?
首先,创建一个处理登录的Action——LoginAction,它负责接收用户信息,进行身份验证,如果验证通过则转入相应的页面,否则,给出错误提示,这是LoginAction处理的基本流程;然后,要构建jsp页面,来负责处理用户登录的界面;最后,进行测试验证,是否符合要求。
LoginAction
下面就来看看LoginAction的实现,这里,需要和jsp页面相配合,要进行相应的控制,就需要相应的属性设置,代码如下:
package cn.lut.curiezhang.action;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Map;
import java.util.ResourceBundle;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.apache.struts2.interceptor.ServletRequestAware;
import org.apache.struts2.interceptor.ServletResponseAware;
import org.apache.struts2.interceptor.SessionAware;
import com.opensymphony.xwork2.ActionSupport;
import cn.lut.curiezhang.model.UserStatus;
import cn.lut.curiezhang.model.Users;
import cn.lut.curiezhang.service.UserService;
@SuppressWarnings("serial")
public class LoginAction extends ActionSupport implements ServletRequestAware, ServletResponseAware, SessionAware {
private static final Logger log = LogManager.getLogger(LoginAction.class);
public static final String USER_SESSION = ResourceBundle.getBundle("Messages").getString("Application.sessionName");
public static final String LOGIN_TIME = ResourceBundle.getBundle("Messages").getString("Application.loginTime");
public static final String SESSION_STUDENT_INTERVAL = ResourceBundle.getBundle("Messages").getString("Application.sessionStudentInterval");
public static final String SESSION_ADMIN_INTERVAL = ResourceBundle.getBundle("Messages").getString("Application.sessionAdminInterval");
@SuppressWarnings("unused")
private HttpServletResponse response;
private HttpServletRequest request;
private Map<String, Object> session;
private String username;
private String password;
private String imageVerificationCode;
public String getImageVerificationCode() {
return imageVerificationCode;
}
public void setImageVerificationCode(String imageVerificationCode) {
this.imageVerificationCode = imageVerificationCode;
}
/**
* -1 还没有登录
* 0 成功
* 1 用户不存在
* 2 用户名或密码错误
* 3 用户名或密码为空
* 4 自动登录错误
* 5 注销
* 6 权限不够
* 7 短信验证码错误
* 8 短信验证码为空
* 9 手机号码与登记的号码不一致
* 10 手机号码为空
* 11 短信验证码没有发送
*/
private int status = -1;
/**
* Struts和Spring整合过程中按名称自动注入的业务层的类
*/
private UserService userService;
public void setUserService(UserService userService) {
log.debug("cmis:Action层 > 注入Service类");
this.userService = userService;
}
/**
* 没有权限
*/
public String noPermission() {
log.debug("cmis:Action层 > 没有权限");
return "noPermission";
}
/**
* 不能访问
*/
public String noAccess() {
log.debug("cmis:Action层 > 不能访问");
return "noAccess";
}
/**
* 登录界面
*/
public String loginUI() {
log.debug("cmis:Action层 > 登录界面");
return SUCCESS;
}
// 用户登录跳转
public String login() {
setStatus(-1);
if(status == 6) {
log.debug("cmis:Action层 > 管理员登录错误,status=6");
String info = ResourceBundle.getBundle("Messages").getString("Login.loginError6");
addActionMessage(info);
setStatus(6);
return "login";
}
if(username == null || username == "" || password == null || password == "") {
log.debug("cmis:Action层 > 用户名或密码为空,status=1");
String info = ResourceBundle.getBundle("Messages").getString("Login.loginError1");
addActionMessage(info);
setStatus(1);
return "login";
}
if(request.getSession().getAttribute("certCode") != null) {
String certCode = request.getSession().getAttribute("certCode").toString();
log.debug("cmis:Action层 > 验证码={}", certCode);
String imageVerificationCode = getImageVerificationCode().trim();
log.debug("cmis:Action层 > 你的验证码={}", imageVerificationCode);
if(imageVerificationCode != null && imageVerificationCode.equalsIgnoreCase(certCode) == false) {
String info = ResourceBundle.getBundle("Messages").getString("Login.loginError13");
addActionMessage(info);
setStatus(13);
return "login";
}
}
log.debug("cmis:Action层 > login imageVerificationCode={}", this.getImageVerificationCode());
String username = "";
String password = "";
if(getUsername() != null)
username = getUsername().trim();
if(getPassword() != null)
password = getPassword().trim();
if (username != null && !"".equals(username) && password != null
&& !"".equals(password)) {
Users user = userService.checkUser(username, password);
if(user == null) {
log.debug("cmis:Action层 > 用户不存在,status=2");
String info = ResourceBundle.getBundle("Messages").getString("Login.loginError2");
addActionMessage(info);
setStatus(2);
return "login";
}
log.debug("cmis:Action层 > login username={}", user.getUserName());
if (user != null) {
// 将user 设置到session中
session.put(USER_SESSION, user);
session.put(LOGIN_TIME, new SimpleDateFormat("yyyy年MM月dd日 HH:mm:ss").format(new Date()));
log.debug("cmis:Action层 > 登录成功,status=0");
if(request.getSession().getAttribute("certCode") != null) {
request.getSession().removeAttribute("certCode");
}
setStatus(0);
if(user.getStatus().equals(UserStatus.STUDENT)) {
request.getSession().setMaxInactiveInterval(Integer.parseInt(SESSION_STUDENT_INTERVAL)*60);//以秒为单位,即在没有活动x分钟后,session将失效
return "student";
}
request.getSession().setMaxInactiveInterval(Integer.parseInt(SESSION_ADMIN_INTERVAL)*60);//以秒为单位,即在没有活动x分钟后,session将失效
if(user.getStatus().equals(UserStatus.ADMINISTRATOR)) {
return "admin";
}
if(user.getStatus().equals(UserStatus.COLLEGE)) {
return "college";
}
if(user.getStatus().equals(UserStatus.SITE)) {
return "site";
}
return SUCCESS;
}
}
log.debug("cmis:Action层 > 管理员登录错误,status=3");
String info = ResourceBundle.getBundle("Messages").getString("Login.loginError3");
addActionMessage(info);
setStatus(3);
return "login";
}
// 用户退出
public String logout() {
HttpSession session = request.getSession(false);
if (session != null) {
session.removeAttribute(USER_SESSION);
session.removeAttribute(LOGIN_TIME);
}
setStatus(5);
log.debug("cmis:Action层 > 注销,status=5");
return "logout";
}
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;
}
public void setServletResponse(HttpServletResponse response) {
this.response = response;
}
public void setSession(Map<String, Object> session) {
this.session = session;
}
public void setServletRequest(HttpServletRequest request) {
this.request = request;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
}
这里用的status,有些标志并没有使用,将来扩展的时候,就可以用到了,当然,你用哪个值来表示什么结果,都没有关系,只要满足要求就好。
图片验证码
在登录时,用到了图片验证码,如何生成图片验证码,这里专门生成了一个类,随机产生验证码和干扰点,并产生图片,代码如下:
package cn.lut.curiezhang.util;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import java.util.ResourceBundle;
import javax.imageio.ImageIO;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
/*生成验证码图片
*/
public class ValidationCode {
private static final Logger log = LogManager.getLogger(ValidationCode.class);
// 验证码图片中可以出现的字符集,可以根据需要修改
private final String CODE_LENGTH = ResourceBundle.getBundle("Messages")
.getString("Application.image.codeLength");
private char mapTable[] = { 'A', 'B', 'D', 'E', 'F', 'G', 'H', 'J', 'L',
'M', 'N', 'Q', 'R', 'T', 'Y', 'a', 'b',
'd', 'e', 'f', 'h', 'i', 'j', 'm', 'n', 'q', 'r', 't', 'y',
'2', '3', '4', '5', '6', '7', '8' };
/*
* 功能:生成彩色验证码图片
* 参数wedth为生成图片的宽度,参数height为生成图片的高度,参数os为页面的输出流
*/
public String getCertPic(int width, int height, OutputStream os) {
if (width <= 0)
width = 200;
if (height <= 0)
height = 60;
BufferedImage image = new BufferedImage(width, height,
BufferedImage.TYPE_INT_RGB);
// 获取图形上下文
Graphics g = image.getGraphics();
// 设定背景颜色
g.setColor(new Color(0xDCDCDC));
g.fillRect(0, 0, width, height);
// 画边框
g.setColor(Color.black);
g.drawRect(0, 0, width - 1, height - 1);
// 随机产生的验证码
String strEnsure = "";
// CODE_LENGTH代表CODE_LENGTH位验证码,如果要产生更多位的验证码,则加大数值
for (int i = 0; i < Integer.parseInt(CODE_LENGTH); ++i) {
strEnsure += mapTable[(int) (mapTable.length * Math.random())];
}
// 将认证码显示到图像中,如果要生成更多位的验证码,增加drawString语句
g.setColor(Color.black);
g.setFont(new Font("Atlantic Inline", Font.PLAIN, 18));
String str = strEnsure.substring(0, 1);
g.drawString(str, 8, 17);
str = strEnsure.substring(1, 2);
g.drawString(str, 20, 15);
str = strEnsure.substring(2, 3);
g.drawString(str, 35, 18);
str = strEnsure.substring(3, 4);
g.drawString(str, 45, 15);
// 随机产生15个干扰点
Random rand = new Random();
for (int i = 0; i < 10; i++) {
int x = rand.nextInt(width);
int y = rand.nextInt(height);
g.drawOval(x, y, 1, 1);
}
// 释放图形上下文
g.dispose();
try {
// 输出图形到页面
ImageIO.write(image, "JPEG", os);
} catch (IOException e) {
return "";
}
return strEnsure;
}
private static int WIDTH = 230;// 设置图片的宽度
private static int HEIGHT = 40;// 设置图片的高度
private void drawBackground(Graphics g) {
g.setColor(new Color(0xDCDCDC));
g.fillRect(0, 0, WIDTH, HEIGHT);
for (int i = 0; i < 120; i++) {
int x = (int) (Math.random() * WIDTH);
int y = (int) (Math.random() * HEIGHT);
int red = (int) (Math.random() * 255);
int green = (int) (Math.random() * 255);
int blue = (int) (Math.random() * 255);
g.setColor(new Color(red, green, blue));
g.drawOval(x, y, 1, 0);
}
}
private void drawRands(Graphics g, char[] rands) {
// g.setColor(Color.BLUE);
Random random = new Random();
int red = random.nextInt(110);
int green = random.nextInt(50);
int blue = random.nextInt(50);
g.setColor(new Color(red, green, blue));
g.setFont(new Font(null, Font.ITALIC | Font.BOLD, 36));
for (int i = 0; i < Integer.parseInt(CODE_LENGTH); i++) {
g.drawString("" + rands[i],
5 + i * (WIDTH / Integer.parseInt(CODE_LENGTH)),
26 + (int) (Math.random() * 4) + 4);
}
}
private char[] generateCheckCode() {
char[] rands = new char[Integer.parseInt(CODE_LENGTH)];
for (int i = 0; i < Integer.parseInt(CODE_LENGTH); i++) {
rands[i] = mapTable[(int) (mapTable.length * Math.random())];
}
return rands;
}
public String getCertPicture(int width, int height, OutputStream os)
throws IOException {
BufferedImage image = new BufferedImage(WIDTH, HEIGHT,
BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
char[] rands = generateCheckCode();
log.debug("cmis:图片验证码 > rands={}", rands);
drawBackground(g);
drawRands(g, rands);
g.dispose();
ImageIO.write(image, "JPEG", os);
return String.valueOf(rands);
}
}
Struts配置
有了LoginAction,就相应进行配置,可以产生struts-login.xml,然后包含到struts.xml中即可,struts-login.xml的代码如下:
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
"http://struts.apache.org/dtds/struts-2.5.dtd">
<struts>
<package name="CEAMSEMS.login" extends="struts-default" namespace="/login">
<global-results>
<!-- 定义名为exception的全局result -->
<result name="noPermission" type="redirect">/admin/error/noPermission.jsp</result>
<result name="noAccess" type="redirect">/error/noAccess.jsp</result>
</global-results>
<!-- START loginAction -->
<action name="noAccess" class="cn.lut.curiezhang.action.LoginAction" method="noAccess">
<result name="noAccess" type="redirect">/error/noAccess.jsp</result>
<interceptor-ref name="basicStack"/>
</action>
<action name="logout" class="cn.lut.curiezhang.action.LoginAction" method="logout">
<result name="success">login.jsp</result>
<result name="logout">login.jsp</result>
<interceptor-ref name="basicStack"/>
</action>
<action name="login" class="cn.lut.curiezhang.action.LoginAction" method="login">
<result name="student" type="redirectAction">../index.jsp</result>
<result name="college" type="redirectAction">../admin/index</result>
<result name="site" type="redirectAction">../admin/index</result>
<result name="admin" type="redirectAction">../admin/index</result>
<result name="success" type="redirectAction">../admin/index</result>
<result name="studentNot">login.jsp</result>
<result name="collegeNot">login.jsp</result>
<result name="siteNot">login.jsp</result>
<result name="fail">login.jsp</result>
<result name="tooUsers">/error/tooUsers.jsp</result>
<result name="login">login.jsp</result>
<result name="input">login.jsp</result>
<interceptor-ref name="basicStack"/>
</action>
<!-- END loginAction -->
</package>
</struts>
要在struts.xml中添加包含信息,代码如下:
<include file="struts-login.xml" />
Messages.properties
请注意,在代码和jsp中,都用到了一些说明信息,这些信息我仍然在Messages.properties中统一说明,在Messages.properties中添加如下代码:
#################### cmis.login ######################
Login.page.title=\u767B\u5F55
Login.welcome=\u6B22\u8FCE\u767B\u5F55
Login.prompt=\u8BF7\u8F93\u5165\u7528\u6237\u540D\u548C\u5BC6\u7801\uFF08<strong class="text-danger">\u8003\u751F\u4E3A\u8003\u751F\u53F7\uFF0C\u9662\u6821\u4E3A\u56FD\u6807\u7801</strong>\uFF09
Login.promptExaminee=\u8BF7\u8F93\u5165\u7528\u6237\u540D\u548C\u5BC6\u7801\uFF0C\u5E76\u83B7\u53D6\u77ED\u4FE1\u9A8C\u8BC1\u7801
Login.username=\u7528\u6237\u540D
Login.password=\u5BC6\u7801
Login.phone=\u624B\u673A\u53F7
Login.image=\u56FE\u7247
Login.imageVerificationCode=\u9A8C\u8BC1\u7801
Login.username.prompt=\u7528\u6237\u540D \u30FB\u30FB\u30FB
Login.password.prompt=\u5BC6\u7801 \u30FB\u30FB\u30FB
Login.phone.prompt=\u624B\u673A\u53F7 \u30FB\u30FB\u30FB
Login.phone.send=\u83B7\u53D6\u9A8C\u8BC1\u7801
Login.image.prompt=\u9A8C\u8BC1\u7801 \u30FB\u30FB\u30FB
Login.image.send=\u770B\u4E0D\u6E05\u695A\uFF0C\u6362\u4E00\u5F20
Login.login=\u767B\u5F55
Login.logout=\u6CE8\u9500
Login.savePassword=\u8BB0\u4F4F\u5BC6\u7801
Login.register=\u8003\u751F\u6CE8\u518C
Login.registerCollege=\u9662\u6821\u6CE8\u518C
Login.findPassword=\u627E\u56DE\u5BC6\u7801
Login.loginError1=\u767B\u5F55\u5931\u8D25\uFF0C\u7528\u6237\u540D\u6216\u5BC6\u7801\u4E3A\u7A7A
Login.loginError2=\u767B\u5F55\u5931\u8D25\uFF0C\u8BF7\u68C0\u67E5\u7528\u6237\u662F\u5426\u53EF\u7528
Login.loginError3=\u767B\u5F55\u5931\u8D25\uFF0C\u7528\u6237\u540D\u6216\u5BC6\u7801\u4E3A\u7A7A
Login.loginError4=\u767B\u5F55\u5931\u8D25\uFF0C\u6CA1\u6709\u627E\u5230Cookie\uFF0C\u6216Cookie\u4E0E\u6570\u636E\u5E93\u4E0D\u4E00\u81F4\uFF0C\u4E0D\u80FD\u81EA\u52A8\u767B\u9646
Login.loginError5=\u5DF2\u6CE8\u9500\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55
Login.loginError6=\u60A8\u6CA1\u6709\u8FD9\u4E2A\u6743\u9650\uFF0C\u8BF7\u91CD\u65B0\u767B\u5F55
Login.loginError7=\u77ED\u4FE1\u9A8C\u8BC1\u7801\u4E0D\u6B63\u786E
Login.loginError8=\u77ED\u4FE1\u9A8C\u8BC1\u7801\u4E3A\u7A7A
Login.loginError9=\u624B\u673A\u53F7\u7801\u4E0E\u767B\u8BB0\u7684\u53F7\u7801\u4E0D\u4E00\u81F4
Login.loginError10=\u624B\u673A\u53F7\u7801\u4E3A\u7A7A
Login.loginError11=\u77ED\u4FE1\u9A8C\u8BC1\u7801\u6CA1\u6709\u53D1\u9001\uFF0C\u4E0D\u80FD\u9A8C\u8BC1
Login.loginError12=\u9A8C\u8BC1\u7801\u7C7B\u77ED\u4FE11\u5C0F\u65F6\u5185\u540C\u4E00\u624B\u673A\u53F7\u53D1\u9001\u6B21\u6570\u4E0D\u80FD\u8D85\u8FC73\u6B21
Login.loginError13=\u9A8C\u8BC1\u7801\u4E0D\u6B63\u786E
Login.loginError14=\u8003\u751F\u767B\u5F55\u5DF2\u9501\u5B9A\uFF0C\u4E0D\u80FD\u767B\u5F55
Login.loginError15=\u9662\u6821\u767B\u5F55\u5DF2\u9501\u5B9A\uFF0C\u4E0D\u80FD\u767B\u5F55
Login.loginError16=\u8003\u70B9\u767B\u5F55\u5DF2\u9501\u5B9A\uFF0C\u4E0D\u80FD\u767B\u5F55
#################### /cmis.login ######################
这里,可能有些标记没有使用,供你在扩展时参考。
登录页面
现在,可以构造登录页面了login.jsp,代码如下:
<!DOCTYPE html>
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib uri="/struts-tags" prefix="s" %>
<% String savePassword = java.util.ResourceBundle.getBundle("Messages").getString("Login.savePassword"); %>
<% String loginLogin = java.util.ResourceBundle.getBundle("Messages").getString("Login.login"); %>
<html lang="zh-CN">
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta charset="UTF-8">
<title><s:text name="Application.name"/> - <s:text name="Login.page.title"/></title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<jsp:include page="../includes/beginning-notheme.jsp" flush="true" />
</head>
<body style="">
<div class="row">
<div class="col-sm-offset-3 col-sm-6 form-box" style="margin-left: 25%;margin-right: 25%;">
<div class="form-top">
<div class="form-top-left">
<h3><a href="${pageContext.request.contextPath}/" title="${Application.homepage}"><i class="fa fa-home"></i></a> <s:text name="Login.welcome"/></h3>
<p><s:text name="Login.prompt"/></p>
</div>
<div class="form-top-right">
<!-- <i class="fa fa-lock"></i> -->
</div>
</div>
<div class="form-bottom">
<s:textfield type="hidden" name="status" cssClass="form-username form-control hidden" id="status" value="%{status}"/>
<s:form role="form" action="login" namespace="/login" method="post" cssClass="login-form" theme="simple" validate="false">
<!-- 记录上一次登录的错误值 -->
<div class="form-group">
<div class="col-sm-3 control-label" style="padding-top:18px;color:#aaa;position: relative; min-height: 1px; padding-right: 15px; padding-left: 15px;float: left;width: 25%;">
<i class="fa fa-user fa-lg"></i> <s:text name="Login.username"/>
</div>
<div class="col-sm-9" style="padding-top:9px;color:#aaa;position: relative; min-height: 1px; padding-right: 15px; padding-left: 15px;float: right;width: 75%;">
<label class="sr-only" for="username"><s:text name="Login.username"/></label>
<input type="text" name="username" placeholder="<s:text name="Login.username.prompt"/>" class="form-username form-control" id="form-username">
</div>
</div>
<div class="form-group">
<label class="col-sm-offset-1 col-sm-11 control-label">
<s:fielderror fieldName="username" /> </label>
</div>
<div class="form-group">
<div class="col-sm-3 control-label" style="padding-top:18px;color:#aaa;position: relative; min-height: 1px; padding-right: 15px; padding-left: 15px;float: left;width: 25%;">
<i class="fa fa-key fa-lg"></i> <s:text name="Login.password"/>
</div>
<div class="col-sm-9" style="padding-top:9px;color:#aaa;position: relative; min-height: 1px; padding-right: 15px; padding-left: 15px;float: left;width: 75%;">
<label class="sr-only" for="password"><s:text name="Login.password"/></label>
<input type="password" name="password" placeholder="<s:text name="Login.password.prompt"/>" class="form-password form-control" id="form-password">
</div>
</div>
<div class="form-group">
<label class="col-sm-offset-1 col-sm-11 control-label">
<s:fielderror fieldName="password" /> </label>
</div>
<div class="form-group">
<div class="col-sm-3 control-label" style="padding-top:18px;color:#aaa;position: relative; min-height: 1px; padding-right: 15px; padding-left: 15px;float: left;width: 25%;">
<i class="fa fa-ban fa-lg"></i> <s:text name="Login.imageVerificationCode"/>
</div>
<div class="col-sm-3" style="padding-top:9px;color:#aaa;position: relative; min-height: 1px; padding-right: 15px; padding-left: 15px;float: left;width: 25%;">
<label class="sr-only" for="imageVerificationCode"><s:text name="Login.image"/></label>
<input type="text" name="imageVerificationCode" placeholder="<s:text name="Login.image.prompt"/>" class="form-phone form-control" id="form-phone">
</div>
<div class="col-sm-6 p-new-in" style="padding-top:9px;color:#aaa;position: relative; min-height: 1px; padding-right: 15px; padding-left: 15px;float: left;width: 50%;">
<span class="p-new-code l-mar-r15">
<a href="javaScript:changeImage();" class="l-color9 reloadImage" title="<s:text name="Login.image.send"/>">
<img src="makePicture.jsp" class="reloadImage" id="reloadImage"
width="300" height="40" alt="<s:text name="Login.image.send"/>"/></a>
</span>
</div>
</div>
<script type="text/javascript">
function changeImage() {
var myimg = document.getElementById("reloadImage");
now = new Date();
myimg.src="makePicture.jsp?code="+now.getTime();
}
</script>
<div class="form-group">
<label class="col-sm-offset-1 col-sm-11 control-label"><s:fielderror fieldName="phone" /> </label>
</div>
<div class="btn-group btn-block" id="rrrr">
<button type="submit" style="width:50%;background: #f50" class="btn btn-warning ladda-button" id="logonbtn"
title="<%= loginLogin %>" data-style="expand-right">
<span class="ladda-label">
<span class="glyphicon glyphicon-log-in"></span> <s:text name="Login.login"/>
</span>
</button>
<button data-autosave="0" data-toggle="autolog" style="width:50%;" type="button" class="btn ladda-button btn-default" id="autolog"
title="<%= savePassword %>" data-style="expand-right">
<span class="ladda-label">
<span class="glyphicon glyphicon-unchecked" id="checkSave"></span> <s:text name="Login.savePassword"/>
</span>
</button>
</div>
<%-- <s:checkbox label="autoLogin" class="d-none" name="userCookie" id="userCookie" value="false"></s:checkbox> --%>
<s:if test="hasActionMessages()">
<div id="logalert" class="badge badge-warning " style="padding-top:0px;padding-bottom:0px;margin-bottom:10px;margin-top:10px;background-color:#900;width:100%;">
<s:actionmessage style="padding-top:0px;padding-bottom:0px;margin-bottom:4px;margin-top:3px;"/>
</div>
</s:if>
</s:form>
<script type="text/javascript">
$(function(){
$('#autolog').click(function(){
var name = this.className;
//alert(name);
if(name.indexOf('btn-default') > 0){
$('#autolog').removeClass('btn-default');
$('#autolog').addClass('btn-warning');
$('#checkSave').removeClass('glyphicon-unchecked');
$('#checkSave').addClass('glyphicon-check');
$('#userCookie').attr("checked",'true');
return;
}
if(name.indexOf('btn-warning') > 0){
$('#autolog').removeClass('btn-warning');
$('#autolog').addClass('btn-default');
$('#checkSave').removeClass('glyphicon-check');
$('#checkSave').addClass('glyphicon-unchecked');
$('#userCookie').removeAttr("checked");
return;
}
});
$('#autolog').blur();
});
</script>
<div>
<a href="${pageContext.request.contextPath}/user/findPassword" class="btn btn-default btn-sm pull-right">
<span class="glyphicon glyphicon-search"></span> <s:text name="Login.findPassword"/>
</a>
<div class="clearfix"></div>
</div>
</div>
</div>
</div>
</body>
</html>
延续了前面的风格,可以嵌入到一个对应的框架中,这里包含的头部处理文件,可以使用前面所使用的头部包含的js、css文件,也可以重新产生一个,我这里只是将原来产生的重新复制了一套,便于将来扩展时,前台处理和后台处理,可以使用不同的风格。
图片验证码页面
要处理图片验证码的生成,需要页面来传递对应的验证码信息,这里创建一个makePicture.jsp页面,代码如下:
<%@page contentType="image/jpeg" %>
<%@page language="java" pageEncoding="utf-8"%>
<jsp:useBean id="image" scope="page" class="cn.lut.curiezhang.util.ValidationCode"/>
<%
out.clear();
out = pageContext.pushBody();
java.io.OutputStream output=response.getOutputStream();
String str = image.getCertPicture(0,0,output);
output.flush();
//将验证码存入session中
session.setAttribute("certCode", str);
%>
这里使用前面创建的ValidationCode.java类来产生验证码图片,在前面的login.jsp页面中调用这里产生的结果,就可以显示验证码了。
运行
现在,就可以部署执行了,登录界面如下图所示:
输入用户名、密码和验证码,例如:admin、111111、rmhb,就可以进入管理员页面,如下图所示:
这里,点击注销,就可以退出系统,回到登录页面,如果登录信息有错,就会显示错误信息,如下图所示:
至此,已经完成用户登录处理了。
在这里,不需要专门产生一个Service类来处理登录流程,当然,也可以这样做,从用户的相关处理中,将checkUser()部分提取出来,放到一个LoginService类中,再在applicationContext.xml中去部署即可,这样,负责管理用户信息的类,其功能更纯粹,只是单纯的处理用户数据的增删改查。
这里供大家思考。