目錄
1.用戶身份認證
在展示訂單確認頁面之前,需要對用戶身份進行認證,要求用戶必須登錄。
1.1功能分析
- 使用springmvc的攔截器實現。需要實現一個接口HandlerInterceptor接口。
- 業務邏輯
- 從cookie中取token。
- 沒有token,需要跳轉到登錄頁面。
- 有token。調用sso系統的服務,根據token查詢用戶信息。
- 如果查不到用戶信息。用戶登錄已經過期。需要跳轉到登錄頁面。
- 查詢到用戶信息。放行。
- 在springmvc.xml中配置攔截器。
1.2攔截器實現
將一些常量放在properties文件中
#cookie中存放token的key
COOKIE_TOKEN_KEY=COOKIE_TOKEN_KEY
#sso服務url
SSO_URL=http://localhost:8088
攔截器是要實現HandlerInterceptor的,我們在taotao-order-web工程的src/main/java目錄下新建一個包com.taotao.order.interceptor並在該包下新建LoginInterceptor攔截器(實現HandlerInterceptor)
package com.taotao.order.interceptor;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;
import com.taotao.common.pojo.TaotaoResult;
import com.taotao.common.utils.CookieUtils;
import com.taotao.sso.service.UserLoginService;
public class LoginInterceptor implements HandlerInterceptor {
@Value("${SSO_URL}")
private String SSO_URL;
@Value("${COOKIE_TOKEN_KEY}")
private String COOKIE_TOKEN_KEY;
@Autowired
private UserLoginService loginService;
/**在進入目標方法之前執行*/
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
//1.從cookie中獲取token
String token = CookieUtils.getCookieValue(request, COOKIE_TOKEN_KEY);
if(StringUtils.isEmpty(token)) {
//2.用戶未登錄,重定向到登陸頁面
response.sendRedirect(SSO_URL+"/page/login");
}
TaotaoResult result = loginService.getUserByToken(token);
if(result.getStatus()!=200) {
//3.用戶已過期,重定向到登陸頁面
response.sendRedirect(SSO_URL+"/page/login");
}else {
//4.用戶已登錄放行
return true;
}
return false;
}
/**在進入目標方法之後,在返回modelandview之前執行*/
/**共用變量的一些設置*/
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) throws Exception {
}
/**返回modelandview之後,渲染到頁面之前*/
/**異常處理 ,清理工作*/
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex)
throws Exception {
}
}
配置攔截器
<!-- 配置用戶身份認證的攔截器攔截訂單確認和訂單相關的處理 -->
<mvc:interceptors>
<mvc:interceptor>
<!-- ** 表示當前路徑及其子路徑 * 只是攔截當前路徑-->
<mvc:mapping path="/order/**"/>
<bean class="com.taotao.order.interceptor.LoginInterceptor"></bean>
</mvc:interceptor>
</mvc:interceptors>
1.3測試訪問
未登錄狀態下,結算購物車
被攔截後,重定向到登陸界面
2.攔截器存在的問題
存在兩個問題:
- 調用SSO服務調用了兩次,分別是在攔截器中調用一次,在controller獲取用戶信息又調用一次。
- 登錄成功後跳轉到了首頁,應當跳轉到訂單確認頁面纔對。
2.1解決調用SSO服務兩次的問題
實際上,只需要在攔截器中調用一次便可以了,調用之後,將用戶信息的數據存放在request域中,等進入目標的方法,可以直接通過request域獲取用戶信息。
在攔截器中,將登錄的用戶TbUser對象放到request域中
從request域中獲取TbUser對象
2.2解決登錄之後跳轉到首頁的問題
當用戶結算購物車的時候,需要登錄,登錄之後應當跳轉到訂單確認頁面,不應該回到首頁。
下面是正常的流程
在taotao-sso-web的login.jsp,我們可以看到一個叫做redirectUrl的變量,如果redirectUrl不爲空,就會location.href=redirectUrl,
跳轉到這個redirectUrl,所以我們可以在攔截器攔截未登錄用戶跳轉http://localhost:8088/page/login時,設置一個參數redirect=http://localhost:8092/order/order-cart.html
比如:
http://localhost:8088/page/login?redirect=http://localhost:8092/order/order-cart.html
然後在taotao-sso-web的controller將redirect接收,並放到model中。
修改taotao-order-web的未登錄用戶攔截器,在跳轉/page/login時加上參數redirect=url
這個地方是request.getRequestURL()不是request.getRequestURI(),小心看走眼
request.getRequestURL()獲取請求的全名,包括協議、域名、ip、端口等
request.getRequestURI()只能獲取端口後的相對路徑
在taotao-sso-web系統中的controller中接收參數redirect,並放到model中
@RequestMapping("/page/{page}")
public String showPage(@PathVariable String page,String redirect,Model model) {
model.addAttribute("redirect", redirect);
return page;
}
2.3測試訪問
啓動工程
未登錄狀態下去結算
可以看到url後面的參數
登錄成功跳轉到訂單確認頁