1.1.1. 功能分析
請求的url:/user/login
請求的方法:POST
參數:username、password,表單提交的數據。可以使用方法的形參接收。
返回值:json數據,使用e3Result包含一個token。
登錄的處理流程:
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.e3.com\sso.e3.com\order.e3.com,可以使用工具類。
8、Cookie的有效期。關閉瀏覽器失效。
9、登錄成功。
1.1.1. Dao層
查詢tb_user表。單表查詢。可以使用逆向工程。
1.1.1. Service層
參數:
1、用戶名:String username
2、密碼:String password
返回值:e3Result,包裝token。
業務邏輯:
1、判斷用戶名密碼是否正確。
2、登錄成功後生成token。Token相當於原來的jsessionid,字符串,可以使用uuid。
3、把用戶信息保存到redis。Key就是token,value就是TbUser對象轉換成json。
4、使用String類型保存Session信息。可以使用“前綴:token”爲key
5、設置key的過期時間。模擬Session的過期時間。一般半個小時。
6、返回e3Result包裝token。
/** * 用戶登錄service * @Auther: jun * @Date: 2018/5/31 0031 14:14 * @Description: */ @Service public class LoginServiceImpl implements LoginService { @Autowired private TbUserMapper tbUserMapper; @Autowired private JedisClient jedisClient; @Value("${SESSION_EXPIRE}") private Integer SESSION_EXPIRE; @Override public E3Result userLogin(String username, String password) { //業務邏輯: //1、判斷用戶名密碼是否正確。 //先判斷用戶名是否存在 TbUserExample example=new TbUserExample(); TbUserExample.Criteria criteria = example.createCriteria(); //使用username作爲查詢條件 criteria.andUsernameEqualTo(username); List<TbUser> users = tbUserMapper.selectByExample(example); /*if (users==null && users.size()==0){ return E3Result.build(400,"用戶名不存在"); }*/ if ( users.size()==0){ return E3Result.build(400,"用戶名不存在"); } //取出用戶信息 TbUser user = users.get(0); //取出的用戶數據中判斷用戶輸入對應的密碼 if (!DigestUtils.md5DigestAsHex(password.getBytes()).equals(user.getPassword())) { return E3Result.build(400,"密碼錯誤"); } //2、登錄成功後生成token。Token相當於原來的jsessionid,字符串,可以使用uuid。 //生成的token是redis中對應的鍵 String token = UUID.randomUUID().toString(); //3、把用戶信息保存到redis。Key就是token,value就是TbUser對象轉換成json。 //不需要帶密碼 user.setPassword(null); jedisClient.set("SESSION:"+token,JsonUtils.objectToJson(user)); //4、使用String類型保存Session信息。可以使用“前綴:token”爲key //5、設置key的過期時間。模擬Session的過期時間。一般一個小時。 jedisClient.expire("SESSION:"+token,SESSION_EXPIRE); //6、返回e3Result包裝token。 return E3Result.ok(token); }
添加resources中一個applicationContent-redis.xml好使用redis緩存這裏我們用的單機版redis
<!--連接池單機版--> <bean id="jedisClientPool" class="com.e3mall.common.jedis.JedisClientPool"> <property name="jedisPool" ref="jedisPool"/> </bean> <bean id="jedisPool" class="redis.clients.jedis.JedisPool"> <constructor-arg name="host" value="192.168.25.128"/> <constructor-arg name="port" value="6379"/> </bean>
applicationContent-service.xml發佈服務
<!--登錄服務--> <dubbo:service interface="com.e3mall.sso.service.LoginService" ref="loginServiceImpl" timeout="600000"/>
引用服務:
springmvc.xml中配置引用服務
<!--用戶登錄服務--> <dubbo:reference interface="com.e3mall.sso.service.LoginService" id="loginService" />
Controller
請求的url:/user/login
請求的方法:POST
參數:username、password,表單提交的數據。可以使用方法的形參接收。
HttpServletRequest、HttpServletResponse
返回值:json數據,使用e3Result包含一個token。
業務邏輯:
1、接收兩個參數。
2、調用Service進行登錄。
3、從返回結果中取token,寫入cookie。Cookie要跨域。
/** * 用戶登錄功能Controller * @Auther: jun * @Date: 2018/5/31 0031 13:53 * @Description: */ @Controller public class LoginController { @Autowired private LoginService loginService; @Value("${TOKEN_KEY}") private String TOKEN_KEY; /** *跳轉到登錄頁面 * @auther: jun * @date: 2018/5/31 0031 13:57 * @param * @return: java.lang.String * @Description: */ @RequestMapping("/page/login") public String showLogin(String redirect, Model model){ //把redirect參數傳遞到jsp頁面 model.addAttribute("redirect",redirect); return "login"; } /** *用戶登錄並將用token寫入cookie * @auther: jun * @date: 2018/5/31 0031 16:01 * @param username,password,request,response * @return: com.e3mall.common.utils.E3Result * @Description: */ @RequestMapping(value = "user/login",method = RequestMethod.POST) @ResponseBody public E3Result login(String username, String password, HttpServletRequest request, HttpServletResponse response){ //調用登錄服務查詢用戶輸入的用戶名和密碼是否存在數據庫中並且是否正確 E3Result result = loginService.userLogin(username, password); //判斷是否登錄成功 if (result.getStatus()==200){ //登錄成功需要將token寫入cookie中 String token = result.getData().toString(); CookieUtils.setCookie(request,response,TOKEN_KEY,token); } //返回結果 return result; } }
登錄成功並且redis有數據
1.1. 通過token查詢用戶信息
1.1.1. 功能分析
請求的url:/user/token/{token}
參數:Stringtoken需要從url中取。
返回值:json數據。使用e3Result包裝Tbuser對象。
業務邏輯:
1、從url中取參數。
2、根據token查詢redis。
3、如果查詢不到數據。返回用戶已經過期。
4、如果查詢到數據,說明用戶已經登錄。
5、需要重置key的過期時間。
6、把json數據轉換成TbUser對象,然後使用e3Result包裝並返回。
1.1.1. Dao層
使用JedisClient對象。
1.1.1. Service層
參數:Stringtoken
返回值:e3Result
/** * token操作Service * @Auther: jun * @Date: 2018/5/31 0031 16:09 * @Description: */ @Service public class TokenServiceImpl implements TokenService { @Autowired private JedisClient jedisClient; @Value("${SESSION_EXPIRE}") private Integer SESSION_EXPIRE; @Override public E3Result getUserByToker(String token) { //根據token在redis中查詢用戶信息 String json = jedisClient.get("SESSION:" + token); //判斷json數據是否爲空 if (StringUtils.isBlank(json)) { //如果爲空 return E3Result.build(201,"用戶登錄信息已經過期,請重新登錄"); } //不爲空說明查詢到了數據,說明用戶已經登錄 //每次使用token訪問是刷新過期時間設置過期時間 jedisClient.expire("SESSION:"+token,SESSION_EXPIRE); //獲取到redis中token對應的用戶信息 TbUser user = JsonUtils.jsonToPojo(json, TbUser.class); //返回結果 return E3Result.ok(user); } }
<!--token服務--> <dubbo:service interface="com.e3mall.sso.service.TokenService" ref="tokenServiceImpl" timeout="600000"/>
引用服務同上的登錄服務一樣引用
<!--token服務--> <dubbo:reference interface="com.e3mall.sso.service.TokenService" id="tokenService" />
Controller
/** * Token Controller * @Auther: jun * @Date: 2018/5/31 0031 16:18 * @Description: */ @Controller public class TokenController { @Autowired private TokenService tokenService; /** *請求的url:/user/token/{token} * 參數:String token需要從url中取。 * 返回值:json * @auther: jun * @date: 2018/5/31 0031 16:21 * @param token * @return: com.e3mall.common.utils.E3Result * @Description: */ /*@RequestMapping(value = "/user/token/{token}",method = RequestMethod.GET, produces =MediaType.APPLICATION_JSON_UTF8_VALUE *//*"application/json;charset=utf-8"*//*) @ResponseBody public String getUserByToken(@PathVariable String token,String callback){ //調用token服務 E3Result result = tokenService.getUserByToker(token); //響應結果之前,判斷是否是jsonp請求(就是判斷callback是否有值) if (StringUtils.isNoneBlank(callback)){ //瓶裝成js語句需要的響應數據json數據 return callback+"("+JsonUtils.objectToJson(result)+");"; } //返回結果 return JsonUtils.objectToJson(result); }*/@RequestMapping(value = "/user/token/{token}",method = RequestMethod.GET) @ResponseBody public Object getUserByToken(@PathVariable String token,String callback){ //調用token服務 E3Result result = tokenService.getUserByToker(token); //響應結果之前,判斷是否是jsonp請求(就是判斷callback是否有值) if (StringUtils.isNoneBlank(callback)){ //瓶裝成js語句響應 MappingJacksonValue mappingJacksonValue=new MappingJacksonValue(result); mappingJacksonValue.setJsonpFunction(callback); return mappingJacksonValue; } //返回結果 return result; } }
1.1.1. 安全退出
需要根據token刪除redis中的key。
jsp頁面
Service
@Override public E3Result logout(String token) { //執行刪除 jedisClient.del ("SESSION:" + token); //返回成功 return E3Result.ok (); }
Controller這裏退出我們選擇了當前用戶所有需要傳一個token值
/** *需要根據token刪除redis中的key * @auther: jun * @date: 2018/6/3 0003 21:17 * @param token * @return: com.e3mall.common.utils.E3Result * @Description: */ @RequestMapping(value = "user/logout/{token}") public String logout(@PathVariable String token){ tokenService.logout(token); return "redirect:/page/login.html"; }
刪除token鍵
這裏沒有紅框鍵了