前言
技術原理
邏輯代碼
1、單點登錄
@RequestMapping(value ="login.do",method = {RequestMethod.POST})
public @ResponseBody JSONObject login(@RequestBody JSONObject loginJson,HttpServletRequest request, HttpServletResponse response){
// 登錄校驗
JSONObject resultJson = userService.login(loginJson);
if (resultJson.getIntValue("result_code") == 0) {
SysUser sysUser =(SysUser) resultJson.get("sysUser");
// 創建登錄Session信息
resultJson.put("id", sysUser.getId());
resultJson.put("name", sysUser.getName());
resultJson.put("loginName", sysUser.getLoginName());
this.initSession(request, sysUser);
logger.info(String.format("用戶:%s 登錄系統,登錄時間:%s", loginJson.getString("loginName")));
}
return resultJson;
}
private void initSession(HttpServletRequest request,SysUser sysUser) {
//創建登錄Session信息
HttpSession httpSession = request.getSession();
httpSession.setAttribute("loginName", sysUser.getLoginName());
httpSession.setAttribute("userId", sysUser.getId());
}
接口實現類UserServiceImpl.java(接口類UserService.java)中的登錄校驗方法,這裏面主要是獲取前臺傳遞的用戶信息參數,再通過用戶名查詢數據庫用戶信息,可能難點是用MD5密碼加密覈對信息進行校驗。public JSONObject login(JSONObject jSONObject){
JSONObject resultJson = new JSONObject();
try {
if(StringUtils.isBlank( jSONObject.getString("loginName"))){
throw new RuntimeException("登錄用戶名不能爲空!");
}
if(StringUtils.isBlank( jSONObject.getString("password"))){
throw new RuntimeException("登錄必須填寫密碼!");
}
String loginName = jSONObject.getString("loginName");
SysUser sysUser = sysUserMapper.findByLoginName(loginName);
if(sysUser==null){
throw new RuntimeException("用戶不存在!");
}
if(StringUtils.isBlank(jSONObject.getString("password"))){
throw new RuntimeException("登錄密碼不能爲空!");
}
String password = MD5Util.getMD5String(jSONObject.getString("password"));
if(StringUtils.isBlank(sysUser.getPassword()) || !sysUser.getPassword().equals((password))){
throw new RuntimeException("密碼錯誤!");
}
resultJson.put("result_code", 0);
resultJson.put("result_detail", "success");
resultJson.put("sysUser", sysUser);
} catch (RuntimeException e){
resultJson.put("result_code", -2);
resultJson.put("result_detail", e.getMessage());
logger.error("login ",e);
}catch (Exception e){
resultJson.put("result_code", -1);
resultJson.put("result_detail", e.getMessage());
logger.error("login ",e);
}
return resultJson;
}
加密工具類MD5Util.javapackage com.kilomob.powernetwork.permission.common;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
/**
*
* @author fengjk
*
*/
public class MD5Util {
private static Log log = LogFactory.getLog(MD5Util.class);
/**
* 默認的密碼字符串組合,apache校驗下載的文件的正確性用的就是默認的這個組合
*/
protected static char hexDigits[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
protected static MessageDigest messagedigest = null;
static {
try {
messagedigest = MessageDigest.getInstance("MD5");
} catch (NoSuchAlgorithmException nsaex) {
log.error(MD5Util.class.getName() + "初始化失敗,MessageDigest不支持MD5Util。");
nsaex.printStackTrace();
}
}
public static String getMD5String(String str){
if(str!=null){
messagedigest.update(str.getBytes());
return bufferToHex(messagedigest.digest());
}else{
return null;
}
}
private static String bufferToHex(byte bytes[]) {
return bufferToHex(bytes, 0, bytes.length);
}
private static String bufferToHex(byte bytes[], int m, int n) {
StringBuffer stringbuffer = new StringBuffer(2 * n);
int k = m + n;
for (int l = m; l < k; l++) {
appendHexPair(bytes[l], stringbuffer);
}
return stringbuffer.toString();
}
private static void appendHexPair(byte bt, StringBuffer stringbuffer) {
char c0 = hexDigits[(bt & 0xf0) >> 4];
char c1 = hexDigits[bt & 0xf];
stringbuffer.append(c0);
stringbuffer.append(c1);
}
}
攔截器配置applicationContext.xml <!-- 類的存放路徑class
ignoreUrlList和interceptro指的是忽略,不攔截-->
<bean id="loginInterceptor" class="com.kilomob.powernetwork.managerweb.interceptor.LoginInterceptor">
<property name="loginPage" value="/login.html"></property>
<property name="ignoreUrlList">
<list>
<value>/api/login.do</value>
<value>/login.html</value>
<value>/api/loginout.do</value>
<value>/api/loginValidate.do</value>
<value>/api/imgcode</value>
<value>/api/vali/imagecode</value>
</list>
</property>
</bean>
<mvc:interceptors>
<mvc:interceptor>
<mvc:mapping path="/**"/>
<mvc:exclude-mapping path="/api/imgcode"/>
<mvc:exclude-mapping path="/api/vali/imagecode"/>
<ref bean="loginInterceptor"/>
</mvc:interceptor>
</mvc:interceptors>
注意此處的loginPage和ignoreUrlList應與下面的攔截類變量名一致。攔截類LoginInterceptor.java
package com.kilomob.powernetwork.managerweb.interceptor;
import java.io.File;
import java.util.List;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.kilomob.powernetwork.managerweb.util.WebConfig;
/**
* @Description:登錄攔截器
* @author: fengjk
* @time:2017年3月20日 下午8:11:25
*/
public class LoginInterceptor implements HandlerInterceptor {
private String loginPage;
private List<String> ignoreUrlList;
public String getLoginPage() {
return loginPage;
}
public void setLoginPage(String loginPage) {
this.loginPage = loginPage;
}
public List<String> getIgnoreUrlList() {
return ignoreUrlList;
}
public void setIgnoreUrlList(List<String> ignoreUrlList) {
this.ignoreUrlList = ignoreUrlList;
}
@Override
public boolean preHandle(HttpServletRequest paramHttpServletRequest,HttpServletResponse paramHttpServletResponse, Object paramObject)throws Exception {
paramHttpServletResponse.addHeader("P3P", "CP=CAO PSA OUR");
String path = paramHttpServletRequest.getRequestURI();
boolean ignore = false;
for (String url : ignoreUrlList) {
if (path.contains(url)) {
ignore = true;
break;
}
}
if (ignore) {
return true;
}
HttpSession httpSession = paramHttpServletRequest.getSession();
if (httpSession.getAttribute("userId") == null && httpSession.getAttribute("loginName") == null) {
paramHttpServletResponse.setContentType("text/html;charset=UTF-8");
paramHttpServletResponse.sendRedirect("http://127.0.0.1:8080/managerweb/login.html");
return false;
}
paramHttpServletRequest.setAttribute("loginName", httpSession.getAttribute("loginName"));
paramHttpServletRequest.setAttribute("userId", httpSession.getAttribute("userId"));
return true;
}
@Override
public void postHandle(HttpServletRequest paramHttpServletRequest,HttpServletResponse paramHttpServletResponse, Object paramObject,ModelAndView paramModelAndView) throws Exception {
}
@Override
public void afterCompletion(HttpServletRequest paramHttpServletRequest,HttpServletResponse paramHttpServletResponse, Object paramObject,Exception paramException) throws Exception {
}
}
2、驗證碼校驗
@RequestMapping(value ="/imgcode",method = {RequestMethod.GET})
public void getImgCode(HttpServletRequest request,HttpServletResponse response) throws IOException {
HttpSession session = request.getSession();
session.removeAttribute("code");
response.setContentType("image/jpeg");
ServletOutputStream sos = response.getOutputStream();
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
BufferedImage image = new BufferedImage(WIDTH, HEIGHT,BufferedImage.TYPE_INT_RGB);
Graphics g = image.getGraphics();
char[] rands = generateCheckCode();
drawBackground(g);
drawRands(g, rands);
g.dispose();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ImageIO.write(image, "JPEG", bos);
byte[] buf = bos.toByteArray();
response.setContentLength(buf.length);
sos.write(buf);
bos.close();
sos.close();
session.setAttribute("code", new String(rands));
}
private void drawBackground(Graphics g) {
g.setColor(new Color(72, 75, 83));
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(new Color(0xe0e0e0));
g.setFont(new Font("Arial", Font.BOLD | Font.ITALIC, 24));
g.drawString("" + rands[0], 1, 27);
g.drawString("" + rands[1], 19, 25);
g.drawString("" + rands[2], 39, 27);
g.drawString("" + rands[3], 58, 26);
}
private char[] generateCheckCode() {
String chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
char[] rands = new char[4];
for (int i = 0; i < 4; i++) {
int rand = (int) (Math.random() * 62);
rands[i] = chars.charAt(rand);
}
return rands;
}
/**
* @Description:校驗驗證碼
* @param imagecode
* @param request
* @param response
* @return
* boolean
* @exception:
* @author: fengjk
* @time:2017年3月27日 下午3:45:12
*/
@RequestMapping(value= "/vali/imagecode/{imagecode}" ,method = {RequestMethod.GET} )
public int valideImage(@PathVariable(name = "imagecode") String imagecode,HttpServletRequest request,HttpServletResponse response) {
HttpSession session = request.getSession();
String code = (String)session.getAttribute("code");
if(code != null && code.toUpperCase().equals(imagecode.toUpperCase())){
return 0;
}
return 1;
}
前臺加載首頁時通過Get方式請求getImgCode方法獲取驗證碼,後臺同時用session保存數據,當校驗驗證碼時,通過valideImage方法校驗,返回0說明校驗成功。