视图层:
首页:index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="root" value="${pageContext.request.contextPath}"></c:set>
<!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>
</head>
<body>
<div id="divcontent">
<div id="divtop">
<c:if test="${empty sessionScope.user}">
<a href="${root}/user?op=loginUser">[用户登录]</a>
</c:if>
<c:if test="${not empty sessionScope.user}">
<img class="imgshow" alt="" src="/upload/${sessionScope.user.uid}" />
${sessionScope.user.maskname}
<a href="${root}/user?op=logoutUser">[安全退出]</a>
</c:if>
<a href="${root}/user?op=registUser">[会员注册]</a>
</div>
</div>
</body>
</html>
登录页面:login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"
pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="root" value="${pageContext.request.contextPath}"></c:set>
<!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>
<style type="text/css">
#tbluser{
width: 400px;
margin: 100px auto;
border-collapse: collapse;
font-size: 15px;
}
.tdtitle{
text-align: right;
color: blue;
}
.info{
color: red;
font-size: 14px;
}
.error{
color: red;
font-size: 15px;
font-weight: bolder;
}
#imgcode{
width: 90px;
height: 40px;
cursor: pointer;
vertical-align: middle;
}
</style>
<script type="text/javascript" src="${root}/static/js/jquery-1.12.4.js"></script>
<script type="text/javascript">
$(function(){
$("input[type='submit']").click(function(){
var name = $("#name").val();
if(name.length==0){
alert("用户名不能为空");
return false;
}
var pwd = $("#pwd").val();
if(pwd.length==0){
alert("密码不能为空");
return false;
}
//验证码
var code = $("#code").val();
if(code.length==0){
alert("验证码不能为空");
return false;
}
var flag = false;
$.ajax({
async:false,
type:"POST",
url:"${root}/auth",
data:{"code":code},
dataType:"json",
success:function(res){
alert(res.message);
if(res.code==200){
flag = true;
}
},
error:function(){
alert("网络延时");
}
});
return flag;
});
$("#imgcode").click(function(){
//浏览器重复请求显存信息 会自动缓存 ->请求url相同 直接获取缓存数据
$(this).attr("src","${root}/auth?"+Math.random());
});
});
</script>
</head>
<body>
<form id="formuser" action="${root}/user" method="post">
<table border="1" id="tbluser">
<tr>
<td class="tdtitle">用户名:</td>
<td>
<input type="text" id="name" name="name" maxlength="20" placeholder="请输入手机号码或用户名" />
</td>
<td>
<span id="spanphone" class="info">用户名不能为空</span>
</td>
</tr>
<tr>
<td class="tdtitle">密码:</td>
<td>
<input type="password" maxlength="20" id="pwd" name="pwd" placeholder="请输入用户密码" />
</td>
<td>
<span id="spanpwd" class="info">密码不能为空</span>
</td>
</tr>
<tr>
<td class="tdtitle">验证码:</td>
<td>
<input type="text" maxlength="6" id="code" placeholder="请输入右侧图片上的字符" />
</td>
<td>
<img id="imgcode" alt="" src="${root}/auth" title="看不清楚换一张">
</td>
</tr>
<tr>
<td class="tdtitle"> </td>
<td>
<input type="hidden" name="op" value="loginUser" />
<input type="submit" value="登录" />
<input type="reset" value="重置" />
</td>
<td>
<span id="spanresult" class="error">
<c:if test="${not empty requestScope.result}">
${requestScope.result.message}
</c:if>
</span>
</td>
</tr>
</table>
</form>
</body>
</html>
控制层
AuthServlet.java
package com.uplooking.controller;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;
import javax.servlet.ServletConfig;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import com.alibaba.fastjson.JSONObject;
import com.uplooking.constant.AuthConsts;
import com.uplooking.constant.ConfigConsts;
import com.uplooking.util.AuthCodeUtils;
import com.uplooking.util.RandomUtils;
/**
* Servlet implementation class AuthServlet
*/
@WebServlet("/auth")
public class AuthServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
/**
* @see HttpServlet#HttpServlet()
*/
public AuthServlet() {
super();
// TODO Auto-generated constructor stub
}
/**
* @see Servlet#init(ServletConfig)
*/
public void init(ServletConfig config) throws ServletException {
// TODO Auto-generated method stub
}
/**
* @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
*/
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
//随机生产验证码
String code = RandomUtils.getNumUpperLowerString(AuthConsts.AUTHCODELENGTH);
System.out.println(code);
//保存 Cookie 浏览器本地存储 非重要信息 只能存储字符串
Cookie cookie = new Cookie(AuthConsts.AUTHCODE, code);
//设置过期时间
cookie.setMaxAge(AuthConsts.AUTHEXPIRY);
response.addCookie(cookie);
AuthCodeUtils.drawAuthCode(code, response.getOutputStream());
}
/**
* @see HttpServlet#doPost(HttpServletRequest request, HttpServletResponse response)
*/
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
request.setCharacterEncoding(ConfigConsts.ENCODING);
response.setCharacterEncoding(ConfigConsts.ENCODING);
response.setContentType(ConfigConsts.CONTENT);
PrintWriter out = response.getWriter();
try {
Map<String, Object> map = new HashMap<String, Object>();
String code = request.getParameter("code");
//比对Cookie中的信息
for(Cookie cookie:request.getCookies()){
if(cookie.getName().equals(AuthConsts.AUTHCODE)){
if(code.equalsIgnoreCase(cookie.getValue())){
map.put(ConfigConsts.CODE, ConfigConsts.SUCCESSCODE);
map.put(ConfigConsts.MESSAGE, AuthConsts.AUTHSUCCESSMESSAGE);
out.write(JSONObject.toJSONString(map));
return;
}
}
}
map.put(ConfigConsts.CODE, AuthConsts.AUTHFAILCODE);
map.put(ConfigConsts.MESSAGE, AuthConsts.AUTHFAILMESSAGE);
out.write(JSONObject.toJSONString(map));
} catch (Exception e) {
e.printStackTrace();
}finally{
out.flush();
out.close();
}
}
}
业务层
UserServiceImpl.java
package com.uplooking.service.impl;
import java.io.File;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import org.apache.ibatis.session.SqlSession;
import org.springframework.util.DigestUtils;
import com.uplooking.constant.ConfigConsts;
import com.uplooking.constant.UserConsts;
import com.uplooking.dao.UserMapper;
import com.uplooking.pojo.UserVO;
import com.uplooking.service.UserService;
import com.uplooking.util.IOUtils;
import com.uplooking.util.MybaitsUtils;
import com.uplooking.util.RandomUtils;
public class UserServiceImpl implements UserService {
@Override
public Map<String, Object> loginUser(String name, String pwd) {
Map<String, Object> map = new HashMap<String, Object>();
SqlSession sqlSession = null;
try {
sqlSession = MybaitsUtils.getSqlSession();
UserMapper userMapper = sqlSession.getMapper(UserMapper.class);
//可以使用 电话号码 或 用户名登录
UserVO userVO = null;
if(Pattern.matches(UserConsts.PHONEPATTERN, name)){
userVO = userMapper.findByPhone(name);
}else{
userVO = userMapper.findByName(name);
}
if(userVO!=null){
//密码匹配
if(userVO.getUpwd().equals(DigestUtils.md5DigestAsHex((pwd+userVO.getUsalt()).getBytes()))){
//状态判断
map.put(ConfigConsts.CODE,ConfigConsts.SUCCESSCODE);
map.put(ConfigConsts.MESSAGE,UserConsts.LOGINUSERSUCCESS);
//封装登录用户信息 -> 控制器中存储到会话中
map.put(ConfigConsts.USER, userVO);
}else{
map.put(ConfigConsts.CODE,UserConsts.PASSWORDERRORCODE);
map.put(ConfigConsts.MESSAGE,UserConsts.PASSWORDERRORMESSAGE);
}
}else{
map.put(ConfigConsts.CODE,UserConsts.NAMENOTEXISTCODE);
map.put(ConfigConsts.MESSAGE,UserConsts.NAMENOTEXISTMESSAGE);
}
} catch (Exception e) {
map.put(ConfigConsts.CODE,ConfigConsts.EXCEPTCODE);
map.put(ConfigConsts.MESSAGE,ConfigConsts.EXCEPTMESSAGE);
e.printStackTrace();
}finally{
MybaitsUtils.closeSqlSession(sqlSession);
}
return map;
}
}
工具类
随机数生成类:RandomUtils.java
package com.uplooking.util;
import java.util.Random;
import org.eclipse.jdt.internal.compiler.ast.NumberLiteral;
public class RandomUtils {
//包含 数字 大写字母 小写字母
private static char[] chrs = null;
private static int numberLength = 10;
private static int numberASCII = 48;
private static int upperLetterLength = 26;
private static int upperLetteASCII = 65;
private static int lowerLetterLength = 26;
private static int lowerLetterASCII = 97;
private static Random random = null;
static{
random = new Random(System.currentTimeMillis()*System.currentTimeMillis());
chrs = new char[numberLength+upperLetterLength+lowerLetterLength];
//数字 0-9
for (int i = 0; i < numberLength; i++) {
chrs[i] = (char)(numberASCII+i);
}
//大写字母
for (int i = 0; i < upperLetterLength; i++) {
chrs[numberLength+i] = (char)(upperLetteASCII+i);
}
//小写字母
for (int i = 0; i < lowerLetterLength; i++) {
chrs[numberLength+upperLetterLength+i] = (char)(lowerLetterASCII+i);
}
}
public static String getNumString(int length){
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < length; i++) {
stringBuilder.append(chrs[random.nextInt(numberLength)]);
}
return stringBuilder.toString();
}
public static String getUpperString(int length){
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < length; i++) {
stringBuilder.append(chrs[numberLength+random.nextInt(upperLetterLength)]);
}
return stringBuilder.toString();
}
public static String getLowerString(int length){
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < length; i++) {
stringBuilder.append(chrs[numberLength+upperLetterLength+random.nextInt(lowerLetterLength)]);
}
return stringBuilder.toString();
}
public static String getNumUpperString(int length){
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < length; i++) {
stringBuilder.append(chrs[random.nextInt(numberLength+upperLetterLength)]);
}
return stringBuilder.toString();
}
public static String getNumUpperLowerString(int length){
StringBuilder stringBuilder = new StringBuilder();
for (int i = 0; i < length; i++) {
stringBuilder.append(chrs[random.nextInt(chrs.length)]);
}
return stringBuilder.toString();
}
}
验证码图片生产类:AuthCodeUtils.java
package com.uplooking.util;
import java.awt.Color;
import java.awt.Font;
import java.awt.Graphics;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;
import javax.imageio.ImageIO;
public class AuthCodeUtils {
public static void drawAuthCode(String code,OutputStream output) throws IOException {
int width=90;
int height=40;
int imageType=BufferedImage.TYPE_INT_RGB;
BufferedImage im = new BufferedImage(width, height, imageType);
Graphics ghs = im.getGraphics();
//背景
int x =0;
int y =0;
ghs.setColor(new Color(236,236,236));
ghs.fillRect(x, y, width, height);
//干扰线
int lines = 10;
ghs.setColor(new Color(54,117,23));
Random random = new Random();
for (int i = 0; i < lines; i++) {
int x1 = random.nextInt(width);
int y1 = random.nextInt(height);
int x2 = random.nextInt(width);
int y2 = random.nextInt(height);
ghs.drawLine(x1, y1, x2, y2);
}
ghs.setFont(new Font("黑体",1,25));
ghs.setColor(new Color(121,55,139));
//左下角
ghs.drawString(code, 20, 35);
ghs.dispose();
String formatName = "jpeg";
ImageIO.write(im, formatName, output);
output.flush();
output.close();
}
}
常量
ConfigConsts.java
package com.uplooking.constant;
public interface ConfigConsts {
String ENCODING = "utf-8";
String CONTENT = "text/html";
String OP = "op";
String INDEX = "index";
String SIZE = "size";
String STEP = "step";
String UPLOADPATH = "upload";
String CODE = "code";
String MESSAGE = "message";
String RESULT = "result";
String USER = "user";
int SUCCESSCODE = 200;
int EXCEPTCODE = 500;
String EXCEPTMESSAGE = "系统异常";
String TIMESTAMPTIME = " 0:00:00";
String[] ALLOWROUTES = {"index.jsp","user","auth"};
}
UserConsts.java
package com.uplooking.constant;
import java.io.File;
public interface UserConsts {
char MASKCHAR = '*';
int MASKNAMESTART = 4;
int MASKPWDSTART = 0;
int MASKSALTSTART = 0;
int MASKPHONESTART = 3;
int MASKPHONELENGTH = 6;
int NAMEUPPERLENGTH = 4;
int SALTLENGTH = 20;
int PHONEEXISTCODE = 401;
String PHONEEXISTMESSAGE = "电话号码已被注册";
String PHONENOTEXISTMESSAGE = "电话号码可以使用";
String PHONEPATTERN = "1[3-9][0-9]{9}";
String REGISTUSERSUCCESS = "用户注册成功";
String REGISTUSERFAIL = "用户注册失败";
int REGISTUSERFAILCODE = 402;
String NAMENOTEXISTMESSAGE = "用户名不存在";
int NAMENOTEXISTCODE = 403;
String PASSWORDERRORMESSAGE = "密码错误";
int PASSWORDERRORCODE = 404;
String LOGINUSERSUCCESS = "用户登录成功";
String REGISTUSER = "registUser";
String SENDCODE = "sendCode";
String EXISTPHONE = "existPhone";
String LOGINUSER = "loginUser";
String LOGOUTUSER = "logoutUser";
String USERDEFAULT = "0";
}
AuthConsts.java
package com.uplooking.constant;
public interface AuthConsts {
int AUTHCODELENGTH = 4;
String AUTHCODE = "authCode";
int AUTHEXPIRY = 300;
String AUTHSUCCESSMESSAGE ="验证码输入正确";
String AUTHFAILMESSAGE ="验证码输入错误";
int AUTHFAILCODE = 601;
}