单点登录实现-Java

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\"}"

你可能感兴趣的:(单点登录实现-Java)