1. 程式人生 > >SSO單點登入redis配置

SSO單點登入redis配置

1  Redis叢集的方式

1.1  切換redis的配置方式

1.  就用6379一個redis

Spring配置檔案中 新增<bean id=”jedis”class=”Jedis.class”></bean>

 

@Autowired

Private Jedis jedis;

 

2.  採用redis的分片

a)  分別使用3臺redis提供服務,.配置檔案參見筆記.

1.2  其他的環境問題

Tomcat:tomcat外掛

Mysql:window中的Mysql

Nginx: 檢查配置檔案  拷貝別人的conf

2  單點登入

2.1  SSO複習

2.1.1    單點中的要素

1.  Ticket:它是一個加密後的密碼(MD5),使用者登入後的憑證

2.  使用者資訊:根據使用者名稱和密碼查詢到的真實的使用者資訊  UserJSON

3.  如何取值

2.1.2    HttpCLient的請求方式

說明:Java操作HTTP請求的API,所以httpClient發出請求時,瀏覽器監聽不到

2.1.3    HttpClient傳參方式

3  使用者登陸實現

3.1  SSO單點登入實現

3.1.1    前臺Controller

//使用者登陸 http://www.jt.com/service/user/doLogin?r=0.582247581950398

   //通過login.jsp檢測登陸的username和password是否正確

   @RequestMapping("/doLogin"

)

   @ResponseBody

   public SysResult doLogin(String username,String password,

         HttpServletRequest request,HttpServletResponseresponse){

      //判斷使用者名稱和密碼是否為null

      if(StringUtils.isEmpty(username) || StringUtils.isEmpty(password)){

         return SysResult.build(201, "使用者名稱密碼不能為空");

      }

      //當前輸入的使用者名稱是正確的

      try {

         //獲取使用者的ticket

         String ticket =

                userService.findUserByUP(username,password);

         //ticket不為空

         if(!StringUtils.isEmpty(ticket)){

            //如果ticket資料不為空 則寫入cookie

            //Cookie[] cookies =request.getCookies();

            //Cookie的名稱必須為 JT_TICKET

         CookieUtils.setCookie(request, response, "JT_TICKET", ticket);

            return SysResult.oK(ticket);

         }

      } catch (Exception e) {

         e.printStackTrace();

      }

      return SysResult.build(201, "使用者登陸失敗");

   }

 

3.1.2    編輯前臺Service

//返回ticket資料

   @Override

   public String findUserByUP(String username, String password) {

      String uri = "http://sso.jt.com/user/login";

      Map<String, String> map = new HashMap<String,String>();

      //注意不要有空格  為了網路中傳遞的速度更快 採用簡單字元傳遞

      map.put("u", username);

      map.put("p", password);

      try {

         String resutJSON = httpClient.doPost(uri,map);

         //判斷資料是否有效  將其轉化為Sysresult物件

         //為了防止data資料為null時,返回的字串為"null"對程式碼產生影響

         SysResult sysResult =

         objectMapper.readValue(resutJSON,SysResult.class);        //判斷SSO返回是否正確

         if(sysResult.getStatus() == 200){

            return (String) sysResult.getData();

        

      } catch (Exception e) {

         e.printStackTrace();

      }

      returnnull;

   }

 

 

3.1.3    編輯單點Controller

/**

    * @RequestParam作用:

    * 表示引數接收時採用 u的關鍵字獲取.將獲取到的value值交給

    *  username屬性

    * @paramusername

    * @parampassword

    * @return

    */

   //http://sso.jt.com/user/login

   @RequestMapping("/login")

   @ResponseBody  //形成的JSON資料 {status=201,msg="",data="null"}

   public SysResult doLogin(@RequestParam("u")String username,

         @RequestParam("p")String password){

      try {

         //獲取ticket資訊

         String ticket = userService.findUserByUP(username,password);

         return SysResult.oK(ticket);

      } catch (Exception e) {

         e.printStackTrace();

      }

     

      return SysResult.build(201, "登入失敗");

   }

 

3.1.4    編輯單點Service

/**

    * 1.驗證使用者名稱和密碼是否正確

    * 2.需要將使用者的明文加密為密文

    * 3.如果使用者資訊校驗通過.準備redis快取資料

    * 4.生成ticket= md5(“JT_TICKET_” + System.currentTime + username

    * 5.將User物件轉化為JSON資料

    * 6.將ticket和UserJSON資料存入redis

    * 7.return 返回ticket

    */

   @Override

   public String findUserByUP(String username, String password) {

     

      //根據使用者名稱和加密後的密碼查詢使用者資訊

      String md5Password = DigestUtils.md5Hex(password);

      User user = userMapper.selectUserByUP(username,md5Password);

     

      //判斷user是否為null

      if(user !=null){

        

         //準備ticket資訊

         String ticket = "JT_TICKET_" + System.currentTimeMillis()

         + user.getUsername();

         //加密ticket

         String md5Ticket = DigestUtils.md5Hex(ticket);

        

         try {

            String userJSON = objectMapper.writeValueAsString(user);

            //將資料存入redis

            jedisCluster.set(md5Ticket, userJSON);

            returnmd5Ticket;

           

         } catch (Exception e) {

            e.printStackTrace();

         }

      }

      returnnull;

   }

 

3.2  登入資料的回顯

3.2.1    分析頁面JS

說明:使用者發出JSONP請求 實現使用者資訊回顯

 

Js檔案在jt.js中第一行.

 

 

說明:

    該JS通過Cookie獲取JT_TICKET資訊.如果TICKET不為null.則會發送AJAX請求.請求USERJSON資料.用於頁面展現.

如果ticket為null,則說明使用者沒有登陸,則不予顯示.

 

3.2.2    使用者資訊的回顯

//根據ticket查詢使用者的JSON資訊

   //http://sso.jt.com/user/query/" +_ticket  JSNP的提交

   @RequestMapping("/query/{ticket}")

   @ResponseBody

   public Object findUserByTicket(@PathVariable String ticket,

         String callback){

      //獲取使用者的JSON資料

      String userJSON = jedisCluster.get(ticket);

     

      MappingJacksonValue jacksonValue =

            new MappingJacksonValue(SysResult.oK(userJSON));

      //設定返回的方法名稱

      jacksonValue.setJsonpFunction(callback);

     

      returnjacksonValue;

     

   }

3.2.3    使用者的登出

思路:

    1.cookie中獲取ticket資訊

    2.刪除redis快取

    3.刪除cookie資訊

    4.跳轉頁面到系統歡迎頁面

 

  實現:

   //使用者的登出操作  //user/logout.html

   //1.cookie中獲取ticket資訊

   //2.刪除redis快取

   //3.刪除cookie資訊

   //4.跳轉頁面到系統歡迎頁面

   @RequestMapping("/logout")

   public String logout(HttpServletRequest request,HttpServletResponseresponse){

     

      String ticket = CookieUtils.getCookieValue(request,"JT_TICKET");

      jedisCluster.del(ticket);

      CookieUtils.deleteCookie(request, response, "JT_TICKET");

     

      //通過重定向的方式返回系統首頁 

      return"redirect:/index.html";

   }

 

 

4  京淘購物車實現

4.1  購物車系統

4.1.1    前臺如何連線購物車

4.2  購物車建立

4.2.1    新建購物車專案

選擇web骨架

 

定義專案名稱 jt-cart

 

4.2.2    引入jar包和引入工具類

引入parent專案

 

依賴工具類檔案

4.2.3    新增tomcat外掛

<!--修改埠號8094  -->

  <build>

      <plugins>

         <plugin>

            <groupId>org.apache.tomcat.maven</groupId>

            <artifactId>tomcat7-maven-plugin</artifactId>

            <version>2.2</version>

            <configuration>

                <port>8094</port>

                <path>/</path>

            </configuration>

         </plugin>

      </plugins>

   </build>

 

 

 

 

4.2.4    修改配置檔案

 

1.  SpringMVC的配置檔案

 

2.  修改Spring的配置檔案

 

3.  修改Spring-mycatis的配置檔案

 

 

 

4.2.5    根據表設計建立tb-cart表

說明:通過PD開啟表設計.通過Sql語句建立jt_cart表

 

1.將sql語句複製到MYsql資料庫中執行即可

    建表完成後新增2條測試資料即可.

 

   

4.2.6    構建POJO物件

@Table(name="tb_cart")

publicclass Cart extendsBasePojo{

   @Id

   @GeneratedValue(strategy=GenerationType.IDENTITY)

   private Long id;   //購物車主鍵資訊

   private Long userId//使用者的id

   private Long itemId//商品的Id

   private String itemTitle;   //商品標題

   private String itemImage;   //商品的首圖

   private Long    itemPrice//商品的價格

   private Integer num;     //商品數量

 

4.2.7    構建Mapper物件

public interface CartMapper extends SysMapper<Cart>{

 

}

 

 

4.2.8    構建Service

@Service

publicclass CartServiceImpl implementsCartService {

  

   @Autowired

   private CartMapper cartMapper;

 

}

 

 

4.2.9    構建Controller

@Controller

publicclass CartController {

  

   @Autowired

   private CartService cartService;

 

}

 

4.2.10  修改nginx

#京淘購物車系統

   server {

      listen80;

      server_namecart.jt.com;

      location/ {

         proxy_passhttp://127.0.0.1:8094;

      }

   }

修改nginx之後重啟nginx

 

 

3.  修改HOST檔案

# 京淘電商環境

127.0.0.1      image.jt.com

127.0.0.1      manage.jt.com

127.0.0.1      www.jt.com

127.0.0.1      sso.jt.com

127.0.0.1      cart.jt.com

127.0.0.1      order.jt.com

 

 

5  購物車實現

5.1  根據userId查詢資訊

5.1.1    介面文件定義

請求方法

GET

URL

http://cart.jt.com/cart/query/{userId}

引數

userId 使用者ID

示例

http://cart.jt.com/cart/query/1

返回值

{

status: 200  //200 成功,201 沒有查到

msg: “OK”  //返回資訊訊息

data:

[1]

0:

{

created: 1418092628000

updated: 1418092628000

id:1

userId:1

itemId:39

itemTitle: “java核心技術

itemImage: http://image.jt.com/images/2015/06/11/20150309118.jpg

itemPrice: 87200

num:1

}

}

 

 

 

 

5.1.2    購物車Controller

/**

    * 任務:根據使用者id查詢購物車資訊

    * url:http://cart.jt.com/cart/query/{userId}

    * 返回SysResult物件 並且data資料中儲存cartList的JSON資料

    */

   @RequestMapping("/query/{userId}")

   @ResponseBody

   public SysResult findCartByUserId(@PathVariable Long userId){

      try {

         //獲取cartList資料

         List<Cart> cartList =

                cartService.findCartByUserId(userId);

         String cartListJSON =

                objcetMapper.writeValueAsString(cartList);

         return SysResult.oK(cartListJSON);

      } catch (Exception e) {

         e.printStackTrace();

         return SysResult.build(201, "查詢失敗");

     

   }

 

 

5.1.3    編輯Service

@Override

   public List<Cart> findCartByUserId(Long userId) {

     

      Cart cart = new Cart();

      cart.setUserId(userId);

      //通過通用Mapper查詢購物車資訊

      returncartMapper.select(cart);

   }

 

5.1.4    模擬訪問

說明:模擬正確的請求,檢視程式碼編輯是否正確.

       

5.1.5    前臺訪問分析

說明:根據頁面請求響應頁面

 

分析頁面元素:

頁面中需要迴圈遍歷CartList集合.從Reqest域中獲取

 

        

 

5.1.6    前臺Controller編輯

@Controller

@RequestMapping("/cart")

publicclass CartController {

  

   @Autowired

   private CartService cartService;

  

  

   //轉向到購物車頁面   /cart/show.html

   @RequestMapping("/show")

   public String findCartByUserId(Model model){

     

      Long userId = 7L;  //暫時寫死UserId後期維護

     

      //查詢購物車列表資訊

      List<Cart> cartList =

            cartService.findCartByUserId(userId);

     

      //將資料寫入request域中

      model.addAttribute("cartList", cartList);

      //轉向cart.jsp頁面

      return"cart";

   }

 

5.1.7    編輯前臺Service

@Service

publicclass CartServiceImpl implementsCartService {

  

   @Autowired

   private HttpClientService httpClient;

  

   privatestatic ObjectMapper objectMapper = new ObjectMapper();

  

  

 

   @Override

   public List<Cart> findCartByUserId(Long userId) {

      String uri = "http://cart.jt.com/cart/query/" + userId;

     

      try {

         String resultJSON = httpClient.doGet(uri);

         //資料data的資料型別是Object ,需要轉化為LIst集合,

         //但是轉化會失敗

         //objectMapper.readValue(resultJSON,SysResult.class);

        

         //通過ObjectMapper 直接獲取json的屬性

         //要求:JSON串必須是物件的JSON{id:1,name:tom}

         //而不能是List/arrayJSON [value1,value2]

        

         //{id:1,name:tom}

         JsonNode jsonNode = objectMapper.readTree(resultJSON);

         //JSON資料轉化為String型別的字串 [{},{},{}]

         String cartListJSON = jsonNode.get("data").asText();

        

         //cartListJSON數轉化為List集合

         Cart[] carts =

      objectMapper.readValue(cartListJSON,Cart[].class);

        

         List<Cart> cartList = Arrays.asList(carts);

        

         returncartList;

        

      } catch (Exception e) {

         e.printStackTrace();

      }

      returnnull;

   }

 

5.2  購物車數量修改

5.2.1    業務介面文件定義

請求方法

GET

URL

http://cart.jt.com/cart/update/num/{userId}/{itemId}/{num}

引數

userId 使用者名稱ID

itemId 商品ID

num 數量

示例

http://cart.jt.com/cart/upadate/num/001/002/2

返回值

{

status: 200

msg: “OK”

data:null

}

 

 

 

5.2.2    編輯修改Controller

//http://cart.jt.com/cart/update/num/{userId}/{itemId}/{num}

   @RequestMapping("/update/num/{userId}/{itemId}/{num}")

   @ResponseBody

   public SysResult updateCartNum(

         @PathVariable Long userId,

         @PathVariable Long itemId,

         @PathVariable Integer num){

      try {

         Cart cart = new Cart();

         cart.setUserId(userId);

         cart.setItemId(itemId);

         cart.setNum(num);

         cartService.updateCartNum(cart);

         return SysResult.oK();

        

      } catch (Exception e) {

         e.printStackTrace();

         return SysResult.build(201,"修改數量失敗");

      }

5.2.3    編輯購物車Service

@Override

   publicvoid updateCartNum(Cart cart) {

      //新增修改時間

      cart.setUpdated(newDate());

      cartMapper.updateNum(cart);

  

 

5.2.4    編輯對映檔案

<mapper namespace="com.jt.cart.mapper.CartMapper">

  

   <!--根據userIditemId修改購物車的數量  -->

  

   <update id="updateNum">

      update tb_cart set num = #{num} where

      user_id = #{userId} and item_id = #{itemId}

   </update>

  

  

</mapper>

     

5.2.5    程式碼模擬測試

說明:根據業務中的路徑測試方法編輯是否正確

 

5.2.6    分析頁面

url:http://www.jt.com/service/cart/update/num/1474391958/101

 

說明:

   數量的修改不需要校驗,Controller返回任意值即可.

5.2.7    編輯前臺Controller

//修改購物車商品數量

   //urlhttp://www.jt.com/service/cart/update/num/1474391958/101

   @RequestMapping("/update/num/{itemId}/{num}")

   @ResponseBody

   public String updateCartNum(@PathVariableLong itemId,

         @PathVariable Integer num){

      Long userId = 7L;  //獲取userId

      Cart cart = new Cart();//為屬性賦值

      cart.setUserId(userId);

      cart.setItemId(itemId);

      cart.setNum(num);

      cartService.updateCartNum(cart);

     

      return"";

   }

 

5.2.8    編輯前臺Service

@Override

   publicvoid updateCartNum(Cart cart) {

      //定義urihttp://cart.jt.com/cart/update/num/{userId}/{itemId}/{num}

      String uri =

            "http://cart.jt.com/cart/update/num/"+cart.getUserId()+

            "/"+cart.getItemId()+"/"+cart.getNum();

      try {

         httpClient.doGet(uri);

      } catch (Exception e) {

         e.printStackTrace();

      }

   }

 

5.2.9    效果展現

說明:當數量增減時,價格也會跟著變化,表示測試成功

 

5.3  商品的刪除

5.3.1    介面文件定義

請求方法

GET

URL

http://cart.jt.com/cart/delete/{userId}/{itemId}

引數

userId 使用者ID

itemId 商品ID

示例

http://cart.jt.com/cart/delete/2/6

返回值

{

status: 200

msg: “OK”

data:null

}

 

 

 

5.3.2    編輯購物車Controller

/**

    * 編輯商品的刪除

    *url:http://cart.jt.com/cart/delete/{userId}/{itemId}

    */

   @RequestMapping("/delete/{userId}/{itemId}")

   @ResponseBody

   public SysResult deleteCart(@PathVariableLong userId,

         @PathVariable Long itemId){

      try {

         cartService.deleteCart(userId,itemId);

         return SysResult.oK();

      } catch (Exception e) {

         e.printStackTrace();

         return SysResult.build(201,"刪除購物車失敗");

     

   }

 

 

5.3.3    定義購物車Service

@Override

   publicvoid deleteCart(Long userId, Long itemId) {

      Cart cart = new Cart();

      cart.setUserId(userId);

      cart.setItemId(itemId);

     

      //呼叫父類的方法規範:呼叫父類的方法時最好新增super

      super.deleteByWhere(cart);

  

5.3.4    模擬刪除操作

5.3.5    前臺的刪除

說明:當前臺數據刪除時,應該再次跳轉到購物車列表頁面.

 

5.3.6    編輯前臺Controller

//刪除購物車   /cart/delete/7.html

   @RequestMapping("/delete/{itemId}")

   public String deleteCart(@PathVariableLong itemId){

     

      Long userId = 7L;

      cartService.deleteCart(userId,itemId);

      //跳轉到購物車列表頁面  滿足springMVC的要求 *.html

      return"redirect:/cart/show.html";

   }

 

5.3.7    編輯前臺Service

@Override

   publicvoid deleteCart(Long userId, Long itemId) {

      //定義uri  進行路徑拼接

      String uri = "http://cart.jt.com/cart/delete/"+userId+"/"+itemId;

      try {

         httpClient.doGet(uri);

      } catch (Exception e) {

         e.printStackTrace();

     

   }

 

6  作業:

1.  實現購物車新增的功能

功能描述:

通過查詢商品詳細頁展現商品資訊.當點選加入購物車時實現該業務邏輯

 

 根據介面文件的規範完成.