天天看點

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

淘淘商城項目_11

    • 1、服務接口實作
      • 1.1、檢查資料是否可用接口開發
        • 1.1.1、功能分析
        • 1.1.2、Dao
        • 1.1.3、Service
        • 1.1.4、釋出服務
        • 1.1.5、引用服務
        • 1.1.6、Controller
        • 1.1.7、測試
      • 1.2、使用者注冊接口開發
        • 1.2.1、功能分析
        • 1.2.2、Dao
        • 1.2.3、Service
        • 1.2.4、釋出服務
        • 1.2.5、引用服務
        • 1.2.6、Controller
        • 1.2.7、測試
      • 1.3、使用者登入接口開發
        • 1.3.1、功能分析
        • 1.3.2、Dao
        • 1.3.3、Service
        • 1.3.4、釋出服務
        • 1.3.5、引用服務
        • 1.3.6、Controller
        • 1.3.7、測試
      • 1.4、通過token查詢使用者資訊接口開發
        • 1.4.1、功能分析
        • 1.4.2、Dao
        • 1.4.3、Service
        • 1.4.4、釋出服務
        • 1.4.5、引用服務
        • 1.4.6、Controller
        • 1.4.7、測試
      • 1.5、安全退出接口開發
        • 1.5.1、功能分析
        • 1.5.2、Dao
        • 1.5.3、Service
        • 1.5.4、釋出服務
        • 1.5.5、引用服務
        • 1.5.6、Controller
        • 1.5.7、測試
    • 2、實作SSO系統的登入注冊功能
      • 2.1、展示登入及注冊頁面及首頁超連結修改
      • 2.2、注冊功能實作
      • 2.3、登入功能實作
    • 3、門戶首頁展示使用者名
      • 3.1、首頁展示使用者名分析
      • 3.2、jsonp原理
      • 3.3、jsonp實作
        • 3.3.1、用戶端:使用ajax自帶的callback函數
        • 3.3.2、服務端:springmvc支援jsonp的兩種實作方法

課程計劃

  • 1、SSO注冊功能實作
  • 2、SSO登入功能實作
  • 3、通過token獲得使用者資訊
  • 4、ajax跨域請求解決方案–jsonp

1、服務接口實作

  

SSO系統就是解決分布式環境下登入問題的,本質上是解決分布式環境下session共享問題。

1.1、檢查資料是否可用接口開發

檢查資料是否可用作為注冊功能的輔助。

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

1.1.1、功能分析

請求的url:/user/check/{param}/{type}

參數:從url中取參數

  1、String param(要校驗的資料)

  2、Integer type(校驗的資料類型)

響應的資料:json資料。TaotaoResult,封裝的資料校驗的結果為true:表示成功,資料可用,false:失敗,資料不可用。

業務邏輯:

  1、從tb_user表中查詢資料。

  2、查詢條件根據傳遞過來的參數動态生成。

  3、判斷查詢結果,如果查詢到資料就傳回false。

  4、如果沒有查詢到資料就傳回true。

  5、使用TaotaoResult包裝,并傳回。

1.1.2、Dao

  從tb_user表查詢。屬于單表查詢,可以使用逆向工程生成的代碼。

1.1.3、Service

先在taotao-sso-interface中定義接口UserRegisterService,

再在taotao-sso-service中寫實作類。

參數:

  1、要校驗的資料:String param

  2、資料類型:Integer type(1、2、3分别代表username、phone、email)

傳回值:TaotaoResult

在taotao-sso-interface建立接口

/**
 * 使用者注冊管理接口
 * @author chenmingjun
 * @date 2018年12月3日 上午9:47:29
 * @version V1.0
 */
public interface UserRegisterService {
	/**
	 * 檢查APP傳過來的資料是否可用
	 * @param param 要校驗的資料
	 * @param type 校驗的資料類型
	 * @return
	 */
	TaotaoResult checkData(String param, Integer type);
}
           

在taotao-sso-service建立實作類

@Autowired
	private TbUserMapper tbUserMapper;
	
	@Override
	public TaotaoResult checkData(String param, Integer type) {
		// 1、從tb_user表中查詢資料
		TbUserExample example = new TbUserExample();
		Criteria criteria = example.createCriteria();
		// 2、查詢條件根據傳遞過來的參數動态生成
		// 1、2、3分别代表username、phone、email
		if (type == 1) {
			criteria.andUsernameEqualTo(param);
		} else if (type == 2) {
			criteria.andPhoneEqualTo(param);
		} else if (type == 3) {
			criteria.andEmailEqualTo(param);
		} else {
			return TaotaoResult.build(400, "傳遞過來的是非法的參數");
		}
		// 執行查詢
		List<TbUser> list = tbUserMapper.selectByExample(example);
		// 3、判斷查詢結果,如果查詢到資料就傳回false
		if (list == null || list.size() == 0) {
			// 4、如果沒有查詢到資料就傳回true
			return TaotaoResult.ok(true);
		}
		// 5、使用TaotaoResult包裝,并傳回
		return TaotaoResult.ok(false);
	}
           

1.1.4、釋出服務

先在taotao-sso-service工程中的pom.xml檔案中配置對taotao-sso-interface的依賴,因為服務層釋出服務要通過該接口,

再在taotao-sso-service工程中的applicationContext-service.xml檔案中釋出服務:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

1.1.5、引用服務

需要在taotao-sso-web中實作。

先在taotao-sso-web工程中的pom.xml檔案中配置對taotao-sso-interface的依賴,表現層調用服務要通過該接口,

在taotao-sso-web工程中的springmvc.xml檔案中引用服務:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

1.1.6、Controller

請求的url:/user/check/{param}/{type}

參數:從url中取參數

  1、String param(要校驗的資料)

  2、Integer type(校驗的資料類型)

請求的方法:get。

響應的資料:json資料。TaotaoResult,封裝的資料校驗的結果,true:成功;false:失敗。

/**
 * 使用者處理Controller
 * @author chenmingjun
 * @date 2018年12月3日 上午10:31:38
 * @version V1.0
 */
@Controller
public class UserController {
	
	@Autowired
	private UserRegisterService userRegisterService;

	@RequestMapping(value="/user/check/{param}/{type}", method=RequestMethod.GET)
	@ResponseBody
	public TaotaoResult checkData(@PathVariable String param, @PathVariable Integer type) {
		TaotaoResult result = userRegisterService.checkData(param, type);
		return result;
	}
}
           

1.1.7、測試

get請求好測試,直接在浏覽器中輸入URL即可。

通路位址:http://localhost:8088/user/check/zhangsan/1

浏覽器報404錯誤,原因是:我們web.xml中配置的是攔截以“.html”為字尾的請求。

我們修改通路位址:http://localhost:8088/user/check/zhangsan/1.html

此時浏覽器報406錯誤。原因如下圖:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

而且如果我們在請求後面加上“.html”的話,等于我們修改了接口開發文檔,這是不行的。

正确的做法是要攔截不帶字尾的請求,我們使用“/”即攔截所有請求,如下圖所示:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

下面我們詳解406錯誤的形成原因?

答:當我們浏覽器出現406錯誤時,90%的原因是因為沒有導入jackson-core-2.4.2.jar這個包。10%的原因是我們請求的URL字尾是“.html”。為什麼呢?

原因是:在springMVC中使用注解@ResponseBody,springMVC認為對于字尾是“.html”的URL請求,服務端傳回的應該也是一個html頁面。但是如果服務端傳回的是一個java對象的話,那麼浏覽器不能将一個java對象轉換成一個html對象,即就會報406錯誤。(

這是一個大坑!

1.2、使用者注冊接口開發

1.2.1、功能分析

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

請求的url:/user/register

參數:表單的資料:username、password、phone、email

傳回值:json資料。TaotaoResult。

接收參數:使用TbUser對象接收。

請求的方法:post

業務邏輯:

  1、使用TbUser接收送出的請求。

  2、補全TbUser其他屬性。

  3、

密碼要進行MD5加密

  4、把使用者資訊插入到資料庫中。

  5、傳回TaotaoResult.ok()。

1.2.2、Dao

  可以使用逆向工程生成的代碼。

1.2.3、Service

在taotao-sso-interface中定義接口UserRegisterService已經定義好了,我們直接添加方法即可。

再在taotao-sso-service中寫實作類,我們已經定義好了,直接實作方法即可。

參數:TbUser

傳回值:TaotaoResult

在taotao-sso-interface建立接口

/**
	 * 使用者注冊
	 * @param tbUser 使用者表
	 * @return
	 */
	TaotaoResult register(TbUser tbUser);
}
           

在taotao-sso-service建立實作類

@Override
	public TaotaoResult register(TbUser tbUser) {
		// 1、校驗使用者名和密碼不能為空
		if (StringUtils.isEmpty(tbUser.getUsername())) {
			return TaotaoResult.build(400, "注冊失敗,使用者名不能為空");
		}
		if (StringUtils.isEmpty(tbUser.getPassword())) {
			return TaotaoResult.build(400, "注冊失敗,密碼不能為空");
		}
		// 2、校驗資料的可用性
		// 2.1 、校驗username是否可用
		TaotaoResult checkData = checkData(tbUser.getUsername(), 1);
		
		if (!(boolean) checkData.getData()) { // 說明username不可用,傳回400
			return TaotaoResult.build(400, "使用者名已被使用");
		}
		// 2.2、校驗phone是否可用
		if (StringUtils.isNotBlank(tbUser.getPhone())) { // 說明phone不為空
			if (!(boolean) checkData.getData()) { // 說明phone不可用,傳回400
				return TaotaoResult.build(400, "手機号已被使用");
			}
		}
		// 2.3、校驗email是否可用
		if (StringUtils.isNotBlank(tbUser.getEmail())) { // 說明email不為空
			if (!(boolean) checkData.getData()) { // 說明email不可用,傳回400
				return TaotaoResult.build(400, "郵箱已被使用");
			}
		}
		
		// 補全TbUser其他屬性
		tbUser.setCreated(new Date());
		tbUser.setUpdated(tbUser.getCreated());
		// 密碼的MD5加密處理
		String password = tbUser.getPassword();
		String md5Password = DigestUtils.md5DigestAsHex(password.getBytes());
		tbUser.setPassword(md5Password);
		
		// 把使用者資訊插入到資料庫中
		tbUserMapper.insertSelective(tbUser);
		return TaotaoResult.ok();
	}
           

1.2.4、釋出服務

  在taotao-sso-service工程中applicationContext-service.xml檔案中釋出服務,上面“1.1.4”中已經釋出過了。不在贅圖!

1.2.5、引用服務

  在taotao-sso-web工程中的springmvc.xml檔案中引用服務,上面“1.1.5”中已經引用過了。不在贅圖!

1.2.6、Controller

請求的url:/user/register

參數:表單的資料:username、password、phone、email

傳回值:json資料。TaotaoResult。

接收參數:使用TbUser對象接收。

請求的方法:post

@RequestMapping(value="/user/register", method=RequestMethod.POST)
	@ResponseBody
	public TaotaoResult register(TbUser tbUser) {
		TaotaoResult result = userRegisterService.register(tbUser);
		return result;
	}
           

1.2.7、測試

post請求不好測試,需要我們建立表單,太麻煩了,我們可以使用一個工具。如下:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

可以使用

restclient-ui-3.5-jar-with-dependencies.jar

測試接口。

點選編輯按鈕,填寫表單送出的content-type:application/x-www-form-urlencoded

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

點選插入參數按鈕,填寫參數後,點選生成。

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

點選送出按鈕,測試開始。

1.3、使用者登入接口開發

1.3.1、功能分析

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

請求的url:/user/login

請求的方法:POST

參數:username、password,表單送出的資料。可以使用方法的形參接收。

傳回值:json資料,使用TaotaoResult包含一個token。

業務邏輯:

登入的業務流程:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

登入的處理流程:

  1、登入頁面送出使用者名密碼。

  2、登入成功後生成token。token相當于原來的jsessionid,字元串,可以使用uuid。

  3、把使用者資訊儲存到redis。key就是token,value就是TbUser對象轉換成的json字元串。

  4、使用String類型儲存session資訊。可以使用

“字首:token”

為key。

  5、設定key的過期時間。模拟session的過期時間。一般半個小時。

  6、把token寫入cookie中。

  7、cookie需要跨域。例如:www.taotao.com\sso.taotao.com\order.taotao.com,可以使用工具類。

  8、cookie的有效期。關閉浏覽器失效。

  9、登入成功。

1.3.2、Dao

  查詢tb_user表。單表查詢。可以使用逆向工程生成的代碼。

1.3.3、Service

參數:

  1、使用者名:String username

  2、密碼:String password

傳回值:TaotaoResult,包裝token。

業務邏輯:

  1、判斷使用者名和密碼是否正确。

  2、登入成功後生成token。token相當于原來的jsessionid,字元串,可以使用uuid。

  3、把使用者資訊儲存到redis。key就是token,value就是TbUser對象轉換成的json串。

  4、使用String類型儲存session資訊。可以使用“字首:token”為key。

  5、設定key的過期時間。模拟session的過期時間。一般半個小時。

  6、傳回TaotaoResult包裝token。

部分代碼:需要設定加載屬性檔案。

在taotao-sso-interface建立接口

/**
 * 使用者登入管理接口
 * @author chenmingjun
 * @date 2018年12月3日 下午6:04:21
 * @version V1.0
 */
public interface UserLoginService {

	/**
	 * 根據使用者名和密碼進行登入,生成token作為key,user作為value
	 * @param username
	 * @param password
	 * @return
	 */
	TaotaoResult login(String username, String password);
}
           

在taotao-sso-service建立實作類

@Service
public class UserLoginServiceImpl implements UserLoginService {

	@Autowired
	private TbUserMapper tbUserMapper;
	
	// 注入jedisClient對象
	@Autowired
	private JedisClient jedisClient;
	
	@Value("${USER_SESSION}")
	private String USER_SESSION;
	
	@Value("${SESSION_EXPIRE}")
	private Integer SESSION_EXPIRE;
	
	@Override
	public TaotaoResult login(String username, String password) {
		// 1、判斷使用者名和密碼是否正确。
		TbUserExample example = new TbUserExample();
		Criteria criteria = example.createCriteria();
		criteria.andUsernameEqualTo(username);
		// 查詢使用者資訊,校驗使用者名
		List<TbUser> list = tbUserMapper.selectByExample(example);
		if (list == null || list.size() == 0) { // 說明沒有查詢到使用者資訊,即使用者名輸入錯誤
			return TaotaoResult.build(400, "使用者名或密碼錯誤");
		}
		// 取出使用者資訊,校驗密碼
		TbUser tbUser = list.get(0);
		if (!DigestUtils.md5DigestAsHex(password.getBytes()).equals(tbUser.getPassword())) { // 說明密碼不正确
			return TaotaoResult.build(400, "使用者名或密碼錯誤");
		}
		
		// 2、登入成功後生成token。token相當于原來的jsessionid,字元串,可以使用uuid。
		String token = UUID.randomUUID().toString();
		// 我們密碼就不要存到redis中了,是以要清空密碼
		tbUser.setPassword(null);
		// 3、把使用者資訊儲存到redis。key就是token,value就是TbUser對象轉換成的json串。
		// 4、使用String類型儲存session資訊。可以使用“字首:token”為key。
		jedisClient.set(USER_SESSION + ":" + token, JsonUtils.objectToJson(tbUser));
		// 5、設定key的過期時間。模拟session的過期時間。一般半個小時。
		jedisClient.expire(USER_SESSION + ":" + token, SESSION_EXPIRE);
		
		// 6、傳回TaotaoResult包裝token。
		return TaotaoResult.ok(token);
	}
}
           

1.3.4、釋出服務

在taotao-sso-service工程中applicationContext-service.xml檔案中釋出服務:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

在taotao-sso-service工程中applicationContext-dao.xml檔案中加載配置檔案:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

配置檔案内容如下:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

1.3.5、引用服務

在taotao-sso-web工程中的springmvc.xml檔案中引用服務:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

1.3.6、Controller

請求的url:/user/login

請求的方法:POST

參數:username、password,表單送出的資料。

因為隻有兩個參數,是以不用使用pojo來接收,可以使用方法的形參接收就可以。

從傳回結果中取出token,寫入cookie。需要使用HttpServletRequest、HttpServletResponse

傳回值:json資料,使用TaotaoResult包含一個token。

業務邏輯:

  1、接收表單送出的兩個參數。

  2、調用Service層的方法進行登入。

  3、從傳回結果中取token,寫入cookie。注意:cookie要跨域。

   

cookie的二級域名跨域需要進行設定

   1)setDomain(),設定一級域名:

    .itcast.cn

    .taotao.com

    .taotao.com.cn

   2)setPath(),設定為“/”

   可以使用工具類。工具類放到taotao-common工程中。

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

   需要加入servlet-api的依賴包:在common項目中的pom.xml中,加入依賴:

<dependency>
    	<groupId>javax.servlet</groupId>
    	<artifactId>servlet-api</artifactId>
    	<scope>provided</scope>
    </dependency>
           

注意:

scope

的值是

provided

,表示

該jar包在運作時使用

編譯時使用

測試時用

,但是

打包的時候不用

,因為該jar包web容器tomcat會提供,如果打包的時候使用該jar包,會

出現沖突

  4、響應資料。json資料。TaotaoResult,其中包含token。

@RequestMapping(value="/user/login", method=RequestMethod.POST)
	@ResponseBody
	public TaotaoResult login(String username, String password, HttpServletRequest request, HttpServletResponse response) {
		// 1、接收表單送出的兩個參數。
		// 2、調用Service層的方法進行登入。
		TaotaoResult result = userLoginService.login(username, password);
		// 3、從傳回結果中取出token,寫入cookie。注意:cookie要跨域。
		if (result.getStatus() == 200) {
			String token = result.getData().toString(); // 從傳回結果中取出token
			CookieUtils.setCookie(request, response, COOKIE_TOKEN_KEY, token);
		}
		return result;
	}
           

在taotao-sso-web工程中springmvc.xml檔案中加載配置檔案:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

配置檔案内容如下:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

1.3.7、測試

使用

restclient-ui-3.5-jar-with-dependencies.jar

測試接口,檢視Body;然後檢視redis伺服器中的key。

1.4、通過token查詢使用者資訊接口開發

1.4.1、功能分析

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

請求的url:/user/token/{token}

參數:String token(需要從url中取)

傳回值:json資料。使用TaotaoResult包裝Tbuser對象。

業務邏輯:

  1、從url中取參數。

  2、根據token查詢redis。

  3、如果查詢不到資料,則傳回使用者已經過期。

  4、如果查詢到資料,則說明使用者已經登入。

  5、需要重置key的過期時間。

  6、把json資料轉換成TbUser對象,然後使用TaotaoResult包裝并傳回。

1.4.2、Dao

  使用JedisClient對象進行查詢。

1.4.3、Service

參數:String token

傳回值:TaotaoResult

在taotao-sso-interface建立接口

/**
	 * 根據token從redis中查詢使用者資訊
	 * @param token
	 * @return
	 */
	TaotaoResult getUserByToken(String token);
           

在taotao-sso-service建立實作類

@Override
	public TaotaoResult getUserByToken(String token) {
		// 2、根據token查詢redis。
		String jsonString = jedisClient.get(USER_SESSION + ":" + token);
		if (StringUtils.isBlank(jsonString)) {
			// 3、如果查詢不到資料,則傳回使用者已經過期。
			return TaotaoResult.build(400, "使用者登入狀态已過期,請重新登入");
		}
		// 4、如果查詢到資料,則說明使用者已經登入。
		// 5、需要重置key(USER_SESSION)的過期時間。
		jedisClient.expire(USER_SESSION + ":" + token, SESSION_EXPIRE);
		// 6、把json資料轉換成TbUser對象,然後使用TaotaoResult包裝并傳回。
		TbUser tbUser = JsonUtils.jsonToPojo(jsonString, TbUser.class);
		return TaotaoResult.ok(tbUser);
		// return TaotaoResult.ok(json);
	}
           

注意:如果傳回的是:return TaotaoResult.ok(json);

那麼傳回的json串中會有轉義字元,如下:

{
"status": 200
"msg": "OK"
"data": "{\"id\":1,\"username\":\"zhangsan\",\"password\":null,\"phone\":\"15800807944\",\"email\":\"[email protected]\",\"created\":1414119176000,\"updated\":1414119179000}"
}
           

這跟我們接口開發文檔中的格式不一樣,接口開發文檔中的格式如下:

{
"status": 200
"msg": "OK"
"data": {"id":1,"username":"zhangzhijun","password":null,"phone":"15800807944","email":"[email protected]","created":1414119176000,"updated":1414119179000}
}
           

1.4.4、釋出服務

  在taotao-sso-service工程中applicationContext-service.xml檔案中釋出服務,上面“1.3.4”中已經釋出過了。不在贅圖!

1.4.5、引用服務

  在taotao-sso-web工程中的springmvc.xml檔案中引用服務,上面“1.3.5”中已經引用過了。不在贅圖!

1.4.6、Controller

請求的url:/user/token/{token}

參數:String token (需要從url中取)

傳回值:json資料。使用TaotaoResult包裝Tbuser對象。

@RequestMapping(value="/user/token/{token}", method=RequestMethod.GET)
	@ResponseBody
	public TaotaoResult getUserByToken(@PathVariable String token) {
		TaotaoResult result = userLoginService.getUserByToken(token);
		return result;
	}
           

1.4.7、測試

get請求好測試,直接在浏覽器中輸入URL即可。

通路位址:http://localhost:8088/user/token/cd3c4925-c780-4e15-b8c2-ca9dc764fe47

1.5、安全退出接口開發

1.5.1、功能分析

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

需要根據token删除redis中對應的key。

從接口文檔可知

url:user/logout/{token}

參數:token

傳回值:由TaotaoResule封裝的資訊"ok"。

1.5.2、Dao

  直接使用RedisClient通路redis。

1.5.3、Service

在taotao-sso-interface建立接口

/**
	 * 根據token從redis删除對應的key
	 * @param token
	 * @return
	 */
	TaotaoResult logout(String token);
           

在taotao-sso-service建立實作類

@Override
	public TaotaoResult logout(String token) {
		jedisClient.expire(USER_SESSION + ":" + token, 0);
		return TaotaoResult.ok();
	}
           

1.5.4、釋出服務

  在taotao-sso-service工程中applicationContext-service.xml檔案中釋出服務,上面“1.3.4”中已經釋出過了。不在贅圖!

1.5.5、引用服務

  在taotao-sso-web工程中的springmvc.xml檔案中引用服務,上面“1.3.5”中已經引用過了。不在贅圖!

1.5.6、Controller

url:user/logout/{token}

參數:token

@RequestMapping(value="/user/logout/{token}", method=RequestMethod.GET)
	@ResponseBody
	public TaotaoResult logout(@PathVariable String token) {
		TaotaoResult result = userLoginService.logout(token);
		return result;
	}
           

1.5.7、測試

安裝taotao-sso,啟動taotao-sso、taotao-sso-web。

從redis中找一個存在的token:70ae13a6-87bb-4e3a-b713-35d7979c4bd8

使用RESETClirnt測試通路,删除token:70ae13a6-87bb-4e3a-b713-35d7979c4bd8 的使用者

提示删除成功!

2、實作SSO系統的登入注冊功能

2.1、展示登入及注冊頁面及首頁超連結修改

第一步:加入靜态檔案及JSP頁面

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

第二步:在taotao-sso-web的springmvc.xml檔案中配置資源映射标簽,即不攔截靜态資源。

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

第三步:點選門戶首頁登入按鈕,浏覽器URL為:

  http://localhost:8084/page/login,報錯:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

第四步:點選門戶首頁的免費注冊按鈕,浏覽器的URL為:

  http://localhost:8084/page/register,報錯:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

由此我們發現,其實登入注冊的URL非常類似:

  http://localhost:8084/page/register

  http://localhost:8084/page/login

是以通過

/page/{page}

的方式請求,通過

URL模闆映射

,使用

@PathVariable注解

即可接收請求,轉發jsp頁面,代碼如下:

使用rsetful,跳轉不同頁面

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

第五步:修改端口号為通路登入注冊的端口号為

8088

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

測試:通過。

2.2、注冊功能實作

/taotao-sso-web/src/main/webapp/WEB-INF/jsp/register.jsp分析:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

送出之前檢查:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

注冊,送出表單:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

分析得出,此時的登入功能應該是可以使用了。

2.3、登入功能實作

/taotao-sso-web/src/main/webapp/WEB-INF/jsp/login.jsp分析:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

文檔加載時,調用方法,一旦點選,則送出表單:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

表單送出:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

分析得出,登入功能也是可以使用的。

3、門戶首頁展示使用者名

3.1、首頁展示使用者名分析

1、在taotao-sso-web工程中,當使用者登入成功後,在cookie中有token資訊。

2、在taotao-portal-web工程中,從cookie中取出token,攜帶token發送格式為jsonp的請求,根據token從taotao-sso-web工程中查詢使用者資訊。

3、把從taotao-sso-web工程中查詢到的使用者名展示到首頁taotao-portal-web工程中。

方案一:在Controller中取cookie中的token資料,調用sso服務查詢使用者資訊。

  缺點:由于淘淘商城首頁footer.jsp,在每個系統中都有,可以在每一個系統的footer.jsp中寫一個ajax發起請求調用目前系統的Controller,設定模型資料,然後展示資料。麻煩!

方案二:當頁面加載完成後使用js取cookie中token的資料,使用ajax請求查詢使用者資訊的JSON資料。隻需要在頁面實作一次即可。

乍一看方案一與方案二是一樣的,其實不是,方案一需要在每一個系統都編寫Controller,方案二隻需要在taotao-sso-web編寫一個Controller即可。而且方案一是立即可行的,但是方案二的服務接口在sso系統中。sso.taotao.com(localhost:8088),在首頁顯示使用者名稱,首頁的域名是www.taotao.com(localhost:8082),使用ajax請求跨域了。

什麼是跨域:

  1、域名不同。

  2、域名相同端口不同。

例如:
    www.taotao.com --> 請求 www.taobao.com  也是跨域
    www.taotao.com --> 請求 sso.taotao.com  也是跨域
    www.taotao.com:8080 --> www.taotao.com:8088  也是跨域
    localhost:8080 --> localhost:8088  也是跨域
    www.taotao.com --> www.taotao.com  不是跨域
           

隻有域名和端口完全一樣才不是跨域。

js不可以跨域請求JSON資料

解決js的跨域問題可以使用jsonp。

jsonp

不是新技術

是跨域的解決方案

。使用js的特性繞過跨域請求,特性:

js可以跨域加載js檔案

3.2、jsonp原理

舉個非常常見的例子,我們在html頭部一般都會引入很多js,甚至我們直接引用線上的js,比如我們引用官方網站的jQuery路徑加載進來也是可以的。jQuery的官方域名與我們的工程所在的域名肯定是不一樣的,但是不影響使用,這就是我們所說的js可以跨域請求js檔案!

即:ajax無法跨域請求别的url,我們可以使用ajax跨域加載js檔案。

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

http://localhost:8088/user/token/4ffd07a2-1f92-4601-94ff-2ab763931018?callback=fun

8088做處理:查詢到JSON資料,拼接成fun({“id”:1});

8082浏覽器加載fun({“id”:1});

調用fun方法,裡面參數就是JSON資料。做相關的處理。

更加詳細的解釋:

參考連結:https://blog.csdn.net/pdsu161530247/article/details/82189866

3.3、jsonp實作

3.3.1、用戶端:使用ajax自帶的callback函數

使用jQuery。

在/taotao-portal-web/src/main/webapp/js/taotao.js中:

使用ajax的dataType : “jsonp”,将success : function當做回調函數。

用戶端是taotao-portal-web工程:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

taotao.js代碼如下:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

3.3.2、服務端:springmvc支援jsonp的兩種實作方法

ajax設定的callback函數,我們在後端就需要封裝一個callback(jsondata),讓前端将jsondata作為參數調用。

方法一:springmvc4.1之前的實作方法

服務端是taotao-sso-web工程:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

方法二:springmvc4.1之後的實作方法

springmvc4.1以後,下面兩行代碼會自動幫我們封裝callback(jsondata)

服務端是taotao-sso-web工程:

day78_淘淘商城項目_11_實作SSO系統的登入注冊功能 + 門戶首頁展示使用者名 + ajax請求跨域問題詳解_匠心筆記

我的GitHub位址:https://github.com/heizemingjun

我的部落格園位址:https://www.cnblogs.com/chenmingjun

我的螞蟻筆記部落格位址:https://blog.leanote.com/chenmingjun

Copyright ©2018~2019 黑澤君

【轉載文章務必保留出處和署名,謝謝!】