單點登入系統的介面開發——淘淘商城(二十四)
工程搭建
- 工程目錄。
- pom.xml中tomcat埠配置為8084。
- web.xml中配置工程的url字尾為 / 。
- RedisDao與rest工程中的相同。
介面開發
- 在taotao-sso中開發,提供介面實現單點登入服務。
- redis.properties中配置redis相關引數,包括資料的key。
redis.host=127.0.0.1
redis.prot=6379
#使用者session的key
REDIS_USER_SESSION_KEY=REDIS_USER_SESSION_KEY
#使用者token過期時間
SSO_SESSION_EXPIRE = 1800
- log4j.properties中配置日誌輸出,輸出到控制檯和檔案。
### set log levels ###
log4j.rootLogger=DEBUG , console , debug
### console ###
log4j.appender.console=org.apache.log4j.ConsoleAppender
log4j.appender.console.layout=org.apache.log4j.PatternLayout
log4j.appender.console.layout.ConversionPattern=%d [%t] %-5p [%c] - %m%n
#org.apache包下輸出INFO
#log4j.logger.org.apache=INFO
### log file ###
log4j.appender.debug=org.apache.log4j.DailyRollingFileAppender
log4j.appender.debug.File=./logs/sso.log
log4j.appender.debug.Append=true
log4j.appender.debug.Threshold=INFO
log4j.appender.debug.layout=org.apache.log4j.PatternLayout
log4j.appender.debug.layout.ConversionPattern=%-d{yyyy-MM-dd HH\:mm\:ss} [%p]-[%c] %m%n
檢查資料可用
需求
- 請求方法:GET
- 請求url:/user/check/{param}/{type}
- 請求引數:
- param,校驗引數。
- type,校驗引數型別,1、2、3分別代表使用者名稱、手機、郵箱。
- callback,查詢字串中,可選,如果有此引數表示此方法為jsonp請求,需要支援jsonp。
- 響應引數:TaoTaoResult,資料為true、false,表示資料是否可用。
{
status: 200, //200 成功
msg: "OK", // 返回資訊訊息
data: false // 返回資料,true:資料可用,false:資料不可用
}
Service層
- 建立UserService和實現類,根據資料內容和型別查詢資料庫,若存在相同資料則資料不可用,否則可用,返回TaoTaoResult包裝結果。
@Service
public class UserServiceImpl implements UserService {
@Value("${REDIS_USER_SESSION_KEY}")
private String REDIS_USER_SESSION_KEY;
@Value("${SSO_SESSION_EXPIRE}")
private Integer SSO_SESSION_EXPIRE;
private static final Logger LOGGER = LoggerFactory.getLogger(UserServiceImpl.class);
@Autowired
private TbUserMapper userMapper;
@Autowired
private RedisDao redisDao;
@Override
public TaotaoResult checkData(String content, Integer type) {
//建立查詢條件
TbUserExample example = new TbUserExample();
Criteria criteria = example.createCriteria();
if (type == 1) {
criteria.andUsernameEqualTo(content);
} else if (type == 2) {
criteria.andPhoneEqualTo(content);
} else {
criteria.andEmailEqualTo(content);
}
//執行查詢
Boolean canBeUse = null;
List<TbUser> userList = userMapper.selectByExample(example);
if (userList == null || userList.size() == 0) {
canBeUse = true;
} else {
canBeUse = false;
}
LOGGER.debug("userList: {}", JsonUtils.objectToJson(userList));
return TaotaoResult.ok(canBeUse);
}
Controller層
- 建立UserController,根據內容和型別呼叫service方法,並注意對jsonp的支援,返回TaoTaoResult,包含是否可用。
@Controller
@RequestMapping("/user")
public class UserController {
private static final Logger LOGGER = LoggerFactory.getLogger(UserController.class);
@Autowired
private UserService userService;
@RequestMapping("/check/{param}/{type}")
@ResponseBody
public Object checkData(@PathVariable String param, @PathVariable Integer type, String callback) {
LOGGER.debug("param: {}, type: {}, callback: {}", param, type, callback);
TaotaoResult result = null;
//引數有效性校驗
if (StringUtils.isBlank(param)) {
result = TaotaoResult.build(400, "內容不能為空");
}
if (type == null) {
result = TaotaoResult.build(400, "型別不能為空");
} else if (type != 1 && type != 2 && type != 3) {
result = TaotaoResult.build(400, "型別錯誤");
}
//校驗出錯
if (result != null) {
return getResult(callback, result);
}
//呼叫服務
try {
result = userService.checkData(param, type);
} catch (Exception e) {
result = TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
return getResult(callback, result);
}
/**
* jsonp呼叫則返回包含TaoTaoResult的js片段,否則返回TaoTaoResult
*/
private Object getResult(String callback, TaotaoResult result) {
if (callback != null) {
//jsonp呼叫
MappingJacksonValue mappingJacksonValue = new MappingJacksonValue(result);
mappingJacksonValue.setJsonpFunction(callback);
LOGGER.debug("jacksonVaule: {}", JsonUtils.objectToJson(mappingJacksonValue));
return mappingJacksonValue;
} else {
return result;
}
}
使用者註冊
需求
- 請求方法:POST
- 請求url:/user/register
- 請求引數:4項表單資料,username、password、phone、email
- 響應引數:TaoTaoResult,包含註冊情況。
{
status: 200,
msg: "OK",
data: null,
}
Service層
- 補全user屬性,插入資料庫,返回TaoTaoResult。
- 使用者密碼需要md5化之後存入資料庫。
@Override
public TaotaoResult addUser(TbUser user) {
user.setCreated(new Date());
user.setUpdated(new Date());
//密碼md5化之後儲存在資料庫
user.setPassword(DigestUtils.md5DigestAsHex(user.getPassword().getBytes()));
userMapper.insert(user);
return TaotaoResult.ok();
}
Controller層
- 接收表單中的使用者資訊,呼叫service層服務,返回TaoTaoResult。
@RequestMapping(value = "/register", method = RequestMethod.POST)
@ResponseBody
public TaotaoResult addUser(TbUser user) {
LOGGER.debug("user: {}", ReflectionToStringBuilder.toString(user));
try {
TaotaoResult result = userService.addUser(user);
return result;
} catch (Exception e) {
return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
}
使用者登入
- 請求方法:POST
- 請求url:/user/login
- 請求引數:username、password
- 響應引數:TaoTaoResult,包含token或者錯誤資訊。
{
status: 200,
msg: "OK",
data: "fe5cb546aeb3ce1bf37abcb08a40493e" //登入成功,返回token
}
Service層
- 根據使用者名稱和密碼,從mysql中查詢使用者,密碼進行md5加密後進行比對。比對成功後說明登入成功,生成一個token(可以使用UUID),並把使用者資訊寫入redis,key為token,value為使用者資訊(不包含密碼)。返回token字串。
@Override
public TaotaoResult userLogin(String username, String password) {
//查詢該使用者
TbUserExample example = new TbUserExample();
Criteria criteria = example.createCriteria();
criteria.andUsernameEqualTo(username);
List<TbUser> userList = userMapper.selectByExample(example);
//使用者不存在
if (userList == null || userList.isEmpty()) {
return TaotaoResult.build(400, "使用者名稱或密碼錯誤");
}
TbUser user = userList.get(0);
String md5 = DigestUtils.md5DigestAsHex(password.getBytes());
//密碼不匹配
if (!user.getPassword().equals(md5)) {
return TaotaoResult.build(400, "使用者名稱或密碼錯誤");
}
//生成使用者token
String token = UUID.randomUUID().toString();
//redis中需要清空使用者的密碼
user.setPassword(null);
//使用者資訊寫入redis
String key = REDIS_USER_SESSION_KEY + ":" + token;
redisDao.set(key, JsonUtils.objectToJson(user));
redisDao.expire(key, SSO_SESSION_EXPIRE);
return TaotaoResult.ok(token);
}
Controller層
- 根據使用者名稱和密碼,呼叫service層,返回TaoTaoResult,包含使用者token。
@RequestMapping(value = "/login", method = RequestMethod.POST)
@ResponseBody
public TaotaoResult userLogin(String username, String password) {
try {
TaotaoResult result = userService.userLogin(username, password);
return result;
} catch (Exception e) {
e.printStackTrace();
return TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
}
查詢使用者資訊
需求
- 請求方法:GET
- 請求ulr:/user/token/{token}
- 請求引數:
- token,使用者登入憑證。
- callback,jsonp回撥方法,查詢字串中,可選,用來支援jsonp。
- 響應引數:TaoTaoResult,包含使用者資訊。
{
status: 200,
msg: "OK",
data: "{"id":1,"username":"zhangzhijun","phone":"15800807944","email":"[email protected]","created":1414119176000,"updated":1414119179000}"
}
Service層
- 接收token,根據token到redis中取使用者資訊。判斷token是否存在,如果不存在說明token非法或者session已過期;存在說明使用者就是正常的登入狀態,返回使用者資訊,同時重置使用者的過期時間。返回值用TaoTaoResult包裝。
@Override
public TaotaoResult getUser(String token) {
//從redis中查詢使用者資訊
String json = redisDao.get(REDIS_USER_SESSION_KEY + ":" + token);
if (StringUtils.isBlank(json)) {
return TaotaoResult.build(400, "此session已經過期,請重新登入");
}
//更新過期時間
redisDao.expire(REDIS_USER_SESSION_KEY + ":" + token, SSO_SESSION_EXPIRE);
return TaotaoResult.ok(JsonUtils.jsonToPojo(json, TbUser.class));
}
Controller層
- 根據token調動service方法,返回包含使用者資訊的TaoTaoResult。並且支援jsonp呼叫。
@RequestMapping("/token/{token}")
@ResponseBody
public Object getUser(@PathVariable String token, String callback) {
TaotaoResult result = null;
try {
result = userService.getUser(token);
} catch (Exception e) {
e.printStackTrace();
result = TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
return getResult(callback, result);
}
使用者退出
需求
- 請求方法:GET
- 請求url:/user/logout/{token}
- 請求引數:token,callback(可選)
- 響應引數:TaoTaoResult
{
status: 200,
msg: "OK",
data: ""
}
Service層
- 接收使用者的token,刪除redis中對應的key,返回TaoTaoResult。
@Override
public TaotaoResult userLogout(String token) {
//刪除redis中的key
String key = REDIS_USER_SESSION_KEY + ":" + token;
redisDao.del(key);
return TaotaoResult.ok();
}
Controller層
- 接收使用者的token,呼叫使用者退出的service層方法,返回操作結果的json,需要支援jsonp呼叫。
@RequestMapping("/logout/{token}")
@ResponseBody
public Object userLogout(@PathVariable String token, String callback) {
LOGGER.debug("token: {}, callback: {}", token, callback);
TaotaoResult result = null;
try {
result = userService.userLogout(token);
} catch (Exception e) {
e.printStackTrace();
result = TaotaoResult.build(500, ExceptionUtil.getStackTrace(e));
}
return getResult(callback, result);
}
介面測試
- 使用postman測試介面,參考:postman批量測試。
- 本專案中post提交表單,編碼方式為application/x-www-form-urlencoded。
- 注意:jsonp的響應實體,以
/**/
開頭。
相關推薦
單點登入系統的介面開發——淘淘商城(二十四)
工程搭建 工程目錄。 pom.xml中tomcat埠配置為8084。 web.xml中配置工程的url字尾為 / 。 RedisDao與rest工程中的相同。 介面開發 在tao
Go遊戲伺服器開發的一些思考(二十八):登入流程(一)
過程與不確定因素 帳號登入是一個跨多個服務程序的一段持續的互動過程。 如IO遊戲,會涉及到的遊戲伺服器有: 登入伺服器 資料庫伺服器 快取伺服器 中心伺服器(很多別名,如CenterServer、WorldServer;也可能是redis、etcd之類的
Android開發系列(二十四):Notification的功能與使用方法
font _id when ice extends 開發 content androi mark 關於消息的提示有兩種:一種是Toast,一種就是Notification。前者維持的時間比較短暫,後者維持的時間比較長。 並且我們尋常手機的應用比方網易、貼吧等等都有非常多
OGG維護優化腳本(二十四)-OGG狀態監控系統--後臺腳本
oracle ogg goldengate 這個簡易監控系統具體是由html實現的後臺沒有數據庫,只有從各臺機器收集並上傳過來的html文件通過定時shell腳本整理並分類到各個目錄,然後通過apache被網頁調用具體更新頻率取決於各數據同步服務器的定時任務運行頻率OGG進程狀態整理腳本這個腳本用
python學習(二十四)開發接口
接口 quest HERE cut eth 學習 ret false 數據庫 模擬一些接口,在接口沒有開發成功前,可以用它來測試 用來查詢數據 1、第一個接口 import flask,json #__name__,代表當前這個python文件 server=flask.
Java開發筆記(二十四)方法的組成形式
經過前面的學習,我們發現演示的Java程式碼越來越複雜,而且每個例子的程式碼都堆在入口方法main內部,這會導致如下問題: 1、一個方法內部堆砌了太多的程式碼行,看著費神,維護起來也吃力; 2、部分程式碼描述的是通用演算法,比如牛頓迭代法、二分查詢法等等,這些通用的演算法程式碼結構固定,
spring深入學習(二十四) IOC 之 深入分析 Aware 介面
doCreateBean() 方法主要幹三件事情: 例項化 bean 物件:createBeanInstance() 屬性注入:populateBean() 初始化 bean 物件:initializeBean() 而初始化 bean 物件時也是幹了三件事情:
Go遊戲伺服器開發的一些思考(二十五):Redis的Docker Swarm部署
痛點 在redis 4出來之前,redis哨兵、redis叢集 是無法通過簡單的方式支援Docker Swarm的。原因是Docker Swarm的NAT埠對映機制,會導致redis無法正確獲取宿主IP、埠。 在redis 4之後,官方通過在redis.co
python學習之網站的編寫(HTML,CSS,JS)(二十四)----------示例,點贊,點讚的同時旁邊出現一個逐漸變大的+1殘影並很快消失
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> <st
UWP開發入門(二十四)—— Win10風格的列印對話方塊
雖然經常看到阿迪王發“看那個開發UWP的又上吊了”的圖……還是忍不住重啟一下這個系列。最近有用到UWP的print API,特地來寫一篇給某軟的這個偉大構想續一秒。 之前的列印對話方塊差不多長成這樣: 而新的Win10風格列印對話方塊是下圖的樣子,包
淘淘商城61-SSO單點登入系統之安全退出介面開發
目錄 1.分析介面文件 從介面文件可知 url:user/logout/{token} 引數:token 返回值:由TaotaoResule封裝的資訊"OK" 2.安全退出介面開發 2.1表現層 2.1.1dao層 直接使
淘淘商城59-SSO單點登入系統之使用者登入介面開發
目錄 1.分析介面文件 請求的url:/user/login 請求的方法:POST 引數:username、password。 返回值:json資料,使用TaotaoResult包含一個token。 2.登入介面實現
單點登入系統架構——淘淘商城(二十三)
SSO 單點登入系統(Single Sign On, SSO):在多個應用系統中,使用者只需要登入一次就可以訪問所有相互信任的應用系統,是目前比較流行的企業業務整合的解決方案之一。
帶你逐步深入瞭解SSM框架——淘淘商城專案之單點登入系統實現
1. 課程計劃 1、 實現單點登入系統 2、 實現使用者的登入功能 3、 實現使用者的註冊功能 2. 單點登入系統分析 2.1. 什麼是SSO SSO英文全稱Single Sign On
單點登入系統開發
一、SSO(單點登入系統簡介) 基本介紹 單點登入SSO(Single Sign On)就是在一個多系統共存的環境下,使用者在一處登入後,就不用在其他系統中登入,也就是使用者的一次登入能得到其他所有系統的信任。單點登入在大型網站裡使用得非常頻繁,例如像阿
許可權管理系統--Bootstrap框架/JasigCAS單點登入/Dubbo介面授權
許可權管理系統介面 部門管理 角色管理 開發語言及技術框架 後臺:Java、MySQL、Dubbo、Spring、SpringMVC、MyBatis、Redis、JasigCAS 前臺:Bootstrap、Jquery(jsTree、jquery.val
windows系統下部署單點登入系統
windows系統單點登入 1:在 D:\software\java\learning\sso\keys 目錄下生成 keystore keytool -genkey -alias mykey -keyalg RSA -keystore D:\software\java\learn
SpringBoot+MyBatis+Redis實現SSO單點登入系統(二)
SpringBoot+MyBatis+Redis實現SSO單點登入系統(二) 三、程式碼 配置檔案配置資料庫,redis等相關的資訊。 # See http://docs.spring.io/spring-boot/docs/current/reference/html
SpringBoot+MyBatis+Redis實現SSO單點登入系統(一)
SpringBoot+MyBatis+Redis實現SSO單點登入系統(一) 一、SSO系統概述 SSO英文全稱Single Sign On,單點登入。SSO是在多個應用系統中,使用者只需要
sso單點登入系統
1 課程計劃 第十一天: sso註冊功能實現 sso登入功能實現 通過token獲得使用者資訊 Ajax跨域請求(jsonp) 2 Sso系統工程搭建 需要建立一個sso服務工程,可以參考e3-manager建立。 e3-