1.页面url
http://www.jt.com/user/login.html
http://www.jt.com/service/user/doLogin?r=0.7464354605534896
同域请求,用HttpClient技术
2.分析页面的JS
/service/user/doLogin
Math.random()随机数防止用户重复提交
contentType请求头设置编码格式
error表示发起的请求有问题
var obj = eval(result);结果转换为对象
obj.status == 200 状态码200表示正常
dataType : "json" json格式回传数据
$("#loginsubmit").click(function () {
var loginUrl = "../uc/loginService";
var flag = validateFunction.FORM_validate();
if (flag) {
var uuid = $("#uuid").val();
$(this).attr({ "disabled": "disabled" });
var _username = $("#formlogin [name=username]").val();
var _password = $("#formlogin [name=password]").val();
$.ajax({
type: "POST",
url: "/service/user/doLogin?r=" + Math.random(),
contentType: "application/x-www-form-urlencoded; charset=utf-8",
data: {username:_username,password:_password},
dataType : "json",
error: function () {
$("#nloginpwd").attr({ "class": "text highlight2" });
$("#loginpwd_error").html("网络超时,请稍后再试").show().attr({ "class": "error" });
$("#loginsubmit").removeAttr("disabled");
$this.removeAttr("disabled");
},
success: function (result) {
if (result) {
var obj = eval(result);
if (obj.status == 200) {
obj.success = "http://www.jt.com/index.html";
var isIE = !-[1,];
if (isIE) {
var link = document.createElement("a");
link.href = obj.success;
link.style.display = 'none';
document.body.appendChild(link);
link.click();
} else {
window.location = obj.success;
}
return;
}else{
$("#loginsubmit").removeAttr("disabled");
verc();
$("#nloginpwd").attr({ "class": "text highlight2" });
$("#loginpwd_error").html("账号或密码错误!").show().attr({ "class": "error" });
}
}
}
});
}
});
编辑Controller jt-web
cookie.setMaxAge(7360024);//7天超时,1小时3600s,1天24h
cookie.setMaxAge(0);//立即删除
cookie.setMaxAge(-1);//当前会话关闭后删除
package com.jt.common.vo;
import java.io.Serializable;
import java.util.List;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
/**
* 京淘商城自定义响应结构
*/
@JsonIgnoreProperties(ignoreUnknown=true)
public class SysResult implements Serializable{
private static final long serialVersionUID = 1L;
// 定义jackson对象
private static final ObjectMapper MAPPER = new ObjectMapper();
// 响应业务状态
/*
* 200 成功
* 201 错误
* 400 参数错误
*/
private Integer status;
// 响应消息
private String msg;
// 响应中的数据
private Object data;
public static SysResult build(Integer status, String msg, Object data) {
return new SysResult(status, msg, data);
}
public static SysResult oK(Object data) {
return new SysResult(data);
}
public static SysResult oK() {
return new SysResult(null);
}
public SysResult() {
}
public static SysResult build(Integer status, String msg) {
return new SysResult(status, msg, null);
}
public SysResult(Integer status, String msg, Object data) {
this.status = status;
this.msg = msg;
this.data = data;
}
public SysResult(Object data) {
this.status = 200;
this.msg = "OK";
this.data = data;
}
public Boolean isOk() {
return this.status == 200;
}
public Integer getStatus() {
return status;
}
public void setStatus(Integer status) {
this.status = status;
}
public String getMsg() {
return msg;
}
public void setMsg(String msg) {
this.msg = msg;
}
public Object getData() {
return data;
}
public void setData(Object data) {
this.data = data;
}
/**
* 将json结果集转化为SysResult对象
*
* @param jsonData json数据
* @param clazz SysResult中的object类型
* @return
*/
public static SysResult formatToPojo(String jsonData, Class> clazz) {
try {
if (clazz == null) {
return MAPPER.readValue(jsonData, SysResult.class);
}
JsonNode jsonNode = MAPPER.readTree(jsonData);
JsonNode data = jsonNode.get("data");
Object obj = null;
if (clazz != null) {
if (data.isObject()) {
obj = MAPPER.readValue(data.traverse(), clazz);
} else if (data.isTextual()) {
obj = MAPPER.readValue(data.asText(), clazz);
}
}
return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 没有object对象的转化
*
* @param json
* @return
*/
public static SysResult format(String json) {
try {
return MAPPER.readValue(json, SysResult.class);
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
/**
* Object是集合转化
*
* @param jsonData json数据
* @param clazz 集合中的类型
* @return
*/
public static SysResult formatToList(String jsonData, Class> clazz) {
try {
JsonNode jsonNode = MAPPER.readTree(jsonData);
JsonNode data = jsonNode.get("data");
Object obj = null;
if (data.isArray() && data.size() > 0) {
obj = MAPPER.readValue(data.traverse(),
MAPPER.getTypeFactory().constructCollectionType(List.class, clazz));
}
return build(jsonNode.get("status").intValue(), jsonNode.get("msg").asText(), obj);
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
package com.jt.web.controller;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.jt.common.po.User;
import com.jt.common.vo.SysResult;
import com.jt.web.service.UserService;
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/{module}")
public String module(@PathVariable String module) {
return module;
}
// service/user/doRegister
@RequestMapping("/doRegister")
@ResponseBody
public SysResult saveUser(User user) {
try {
userService.saveUser(user);
return SysResult.oK();
} catch (Exception e) {
e.printStackTrace();
}
return SysResult.build(201, "用户注册失败");
}
/**
* 实现用户登录
* @param user
* @return
* 核心:将用户token秘钥写入到浏览器cookie中
* cookie.setMaxAge(7*3600*24);//7天超时,1小时3600s,1天24h
* cookie.setMaxAge(0);//立即删除
* cookie.setMaxAge(-1);//当前会话关闭后删除
*/
@RequestMapping("/doLogin")
@ResponseBody
public SysResult findUserByUP(User user,HttpServletResponse response){
try {
String token=userService.findUserByUP(user);
if(StringUtils.isEmpty(token)){
return SysResult.build(201, "用户名或密码错误");
}
//如果程序执行到这里表示token一定不为null,将数据写入Cookie
Cookie cookie=new Cookie("JT_TICKET", token);
cookie.setMaxAge(7*3600*24);//7天超时,1小时3600s,1天24h
cookie.setPath("/"); //表示Cookie的所有者
response.addCookie(cookie);//将Cookie写入浏览器
return SysResult.oK();
} catch (Exception e) {
e.printStackTrace();
}
return SysResult.build(201, "用户名或密码错误");
}
}
package com.jt.web.service;
import com.jt.common.po.User;
public interface UserService {
int saveUser(User user);
String findUserByUP(User user);
}
com.jt.web.service.UserServiceImpl
@Override
public String findUserByUP(User user) {
String url="http://sso.jt.com/user/login";
String token=null;
Mapparams=new HashMap();
params.put("username", user.getUsername());
//根据需求实现 应该加密后传输
String md5Pass=DigestUtils.md5Hex(user.getPassword());
System.out.println("user"+user.getUsername()+"pass"+md5Pass);
params.put("password", md5Pass);
//发起http请求
String resultJSON=httpClient.doPost(url, params);
System.out.println("resultJSON"+resultJSON);
try {
SysResult sysResult = objectMapper.readValue(resultJSON, SysResult.class);
if(sysResult.getStatus()==200)
{
token=(String) sysResult.getData();
System.out.println("token"+token);
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException();
}
return token;
}
package com.jt.web.service;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jt.common.po.User;
import com.jt.common.service.HttpClientService;
import com.jt.common.vo.SysResult;
@Service
public class UserServiceImpl implements UserService{
@Autowired
private HttpClientService httpClient;
private static ObjectMapper objectMapper=new ObjectMapper();
@Override
public int saveUser(User user) {
//定义远程url
String url="http://sso.jt.com/user/register";
Mapparams=new HashMap();
params.put("username", user.getUsername());
params.put("password", user.getPassword());
params.put("phone", user.getPhone());
params.put("email", user.getEmail());
String sysResultJSON = httpClient.doPost(url, params);
//如何保证后台程序执行正确
try {
SysResult sysResult = objectMapper.readValue(sysResultJSON, SysResult.class);
if(sysResult.getStatus()!=200)
{
throw new RuntimeException();
}
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException();
}
return 1;
}
/**
* 1.定义url
* 2.封装参数 Map
* 3.发起请求之后校验用户返回值是否正确,
* 获取token数据
* 4.将正确的数据返回
*/
@Override
public String findUserByUP(User user) {
String url="http://sso.jt.com/user/login";
String token=null;
Mapparams=new HashMap();
params.put("username", user.getUsername());
//根据需求实现 应该加密后传输
String md5Pass=DigestUtils.md5Hex(user.getPassword());
System.out.println("user"+user.getUsername()+"pass"+md5Pass);
params.put("password", md5Pass);
//发起http请求
String resultJSON=httpClient.doPost(url, params);
System.out.println("resultJSON"+resultJSON);
try {
SysResult sysResult = objectMapper.readValue(resultJSON, SysResult.class);
if(sysResult.getStatus()==200)
{
token=(String) sysResult.getData();
System.out.println("token"+token);
}
} catch (IOException e) {
e.printStackTrace();
throw new RuntimeException();
}
return token;
}
}
@RequestMapping("/login")
@ResponseBody
public SysResult findUserByUP(User user){
try {
String token=userService.findUserByUP(user);
if(!StringUtils.isEmpty(token))
return SysResult.oK(token);
} catch (Exception e) {
e.printStackTrace();
}
return SysResult.build(201, "用户或密码错误");
}
package com.jt.sso.service;
import com.jt.common.po.User;
public interface UserService {
boolean findCheckUser(String param, Integer type);
int saveUser(User user);
String findUserByUP(User user);
}
package com.jt.sso.mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import com.jt.common.mapper.SysMapper;
import com.jt.common.po.User;
public interface UserMapper extends SysMapper{
int findCheckUser(@Param("column")String column,@Param("param") String param);
@Select("select * from tb_user where username=#{username} and password =#{password}")
User findUserByUP(User user);
}
package com.jt.sso.service;
import java.util.Date;
import org.apache.commons.codec.digest.DigestUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.jt.common.po.User;
import com.jt.sso.mapper.UserMapper;
import redis.clients.jedis.JedisCluster;
@Service
public class UserServiceImpl implements UserService{
@Autowired
private UserMapper userMapper;
private static ObjectMapper objectMapper=new ObjectMapper();
@Autowired
private JedisCluster jedisCluster;
/**
* 1 username 2 phone 3 email
* sql:select count(*) from tb_user where username=#{param}
* 有数据结果一定不为0
*/
@Override
public boolean findCheckUser(String param, Integer type) {
//将type转转化为具体的字段
String column=null;
switch (type) {
case 1:
column="username";
break;
case 2:
column="phone";
break;
case 3:
column="email";
break;
}
//获取用户记录总数
int count=userMapper.findCheckUser(column,param);
//true用户已存在,false用户不存在
return count==0?false:true;
}
/**
* 补全数据
*/
@Override
public int saveUser(User user) {
//将密码进行加密 理论上 密码+盐值
String md5Pass=DigestUtils.md5Hex(user.getPassword());
user.setPassword(md5Pass);;
user.setEmail(user.getPhone()+"@163.com");//暂时代替
user.setCreated(new Date());
user.setUpdated(user.getCreated());
int rows = userMapper.insert(user);
System.out.println("注册 "+rows);
return rows;
}
/**
* 1.根据用户名和密码查询数据库
* 如果结果为null 表示用户名或密码错误 throw
* 2.如果用户信息不为null
* 生成加密的token
* 将user对象转换为JSON
* 将token:json存入redis集群中
* 将token数据返回
*/
@Override
public String findUserByUP(User user) {
User userDB=userMapper.findUserByUP(user);
if(userDB==null){
throw new RuntimeException();
}
String token=DigestUtils.md5Hex("JT_TICKET_"+System.currentTimeMillis()+user.getUsername());
try {
String userJSON=objectMapper.writeValueAsString(userDB);
jedisCluster.setex(token, 7*3600*24, userJSON);
} catch (JsonProcessingException e) {
e.printStackTrace();
throw new RuntimeException();
}
return token;
}
}
用户信息回显
jt.js
var TT = JT = {
checkLogin : function(){
var _ticket = $.cookie("JT_TICKET");
if(!_ticket){
return ;
}
//当dataType类型为jsonp时,jQuery就会自动在请求链接上增加一个callback的参数
$.ajax({
url : "http://sso.jt.com/user/query/" + _ticket,
dataType : "jsonp",
type : "GET",
success : function(data){
if(data.status == 200){
var _data = JSON.parse(data.data);
var html =_data.username+",欢迎来到京淘![退出]";
$("#loginbar").html(html);
}
}
});
}
}
$(function(){
// 查看是否已经登录,如果已经登录查询登录信息
TT.checkLogin();
});
编辑后台controller
//根据token数据查询用户信息
@RequestMapping("/query/{token}")
@ResponseBody
public MappingJacksonValue findUserByToken(@PathVariable String token,String callback){
String userJSON=jedisCluster.get(token);
MappingJacksonValue jacksonValue=null;
if(StringUtils.isEmpty(userJSON))
{
//如果缓存数据没有则直接201返回即可
jacksonValue=new MappingJacksonValue(SysResult.build(201, "用户查询失败"));
}else{
jacksonValue=new MappingJacksonValue(SysResult.oK(userJSON));
}
jacksonValue.setJsonpFunction(callback);
return jacksonValue;
}
package com.jt.sso.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.converter.json.MappingJacksonValue;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import com.jt.common.po.User;
import com.jt.common.vo.SysResult;
import com.jt.sso.service.UserService;
import redis.clients.jedis.JedisCluster;
@Controller
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@Autowired
private JedisCluster jedisCluster;
/**
* 完成用户信息的校验
* url:http://sso.jt.com/user/check/{param}/{type}
* @return
*/
@RequestMapping("/check/{param}/{type}")
@ResponseBody
public MappingJacksonValue findCheckUser(@PathVariable String param,@PathVariable Integer type,String callback){
//true表示数据存在 false表示数据不存在
boolean flag=userService.findCheckUser(param,type);
SysResult sysResult=SysResult.oK(flag);
MappingJacksonValue jacksonValue=new MappingJacksonValue(sysResult);
jacksonValue.setJsonpFunction(callback);
return jacksonValue;
}
@RequestMapping("/register")
@ResponseBody
public SysResult saveUser(User user)
{
try {
userService.saveUser(user);
return SysResult.oK();
} catch (Exception e) {
e.printStackTrace();
}
return SysResult.build(201, "用户注册失败");
}
@RequestMapping("/login")
@ResponseBody
public SysResult findUserByUP(User user){
try {
String token=userService.findUserByUP(user);
if(!StringUtils.isEmpty(token))
return SysResult.oK(token);
} catch (Exception e) {
e.printStackTrace();
}
return SysResult.build(201, "用户或密码错误");
}
//根据token数据查询用户信息
@RequestMapping("/query/{token}")
@ResponseBody
public MappingJacksonValue findUserByToken(@PathVariable String token,String callback){
String userJSON=jedisCluster.get(token);
MappingJacksonValue jacksonValue=null;
if(StringUtils.isEmpty(userJSON))
{
//如果缓存数据没有则直接201返回即可
jacksonValue=new MappingJacksonValue(SysResult.build(201, "用户查询失败"));
}else{
jacksonValue=new MappingJacksonValue(SysResult.oK(userJSON));
}
jacksonValue.setJsonpFunction(callback);
return jacksonValue;
}
}
[root@localhost sentinel]# redis-cli -p 7003
127.0.0.1:7003> keys *
1) "352ce0cb465a1dce58cd15011115992e"
127.0.0.1:7003> get 352ce0cb465a1dce58cd15011115992e
"{\"created\":1515924386000,\"updated\":1515924386000,\"id\":7,\"username\":\"admin123\",\"password\":\"a66abb5684c45962d887564f08346e8d\",\"phone\":\"17600336886\",\"email\":\"17600336886\"}"