Cgb2005 - Beijing Taobao 18 (Dubbo transformation of Beijing Taobao project), users register single sign on user name, echo the rules for users to exit MD5 encrypted page location, cookie tool API, the difference between null and empty string

Cool breeze AAA 2022-02-13 07:43:01 阅读数:706

cgb2005 cgb beijing taobao dubbo

matters needing attention

null , empty , " " The difference between
String nullString = null; Not even an object
String isEmptyString = new String(); There are objects , There is no value in the object
String blackString = " "; There are objects , The value of the object is an empty string
The array string is not empty : if(array! = null ||array.length> 0)
int [] array The reference type is equlas
The condition that the array is empty : if(array== null ||array.length== 0)
String str
The condition that the string is empty : if(str == null ||str.length() ==0);
StringUtils.isEmpty(userJSON)

1 Jingtao project Dubbo Transform to microservice Architecture Only transform sso Act as a consumer
Build the project structure jar package yml file
2 User module implementation : User registration Introduction to the principle of single sign on User login echo User exit operation
User registration : Co domain request (Dubbo Microservice remote invocation implementation ) MD5 encryption Rules for locating pages
Dubbo Unique to the project POJO Abnormal transformation
Introduction to the principle of single sign on ( Microservice architecture ) — adopt cookie and redis Realization uuid random number voucher
see cookie Information cookieApi
User login echo ( Cross domain ): User pass cookie Information query user data . Because after the user logs in successfully, the data is saved in redis in , So it's actually through ticket obtain redis Business data in (k-v structure , according to k obtain v)
encapsulation cookie Tools for Api, Then reconstruct single sign on and user login echo
User exit operation : Redirect to home page

1 Jingtao project Dubbo reform

1.1 Renovation plan ( Build the project structure first )

1.jt-common Act as interface project
2.jt-sso Act as a provider
3.jt-manage Act as a provider
4.jt-web Consumers who act as users

1.2 add to jar Package file (jt)

 Insert picture description here

 <dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>0.2.0</version>
</dependency>

1.3 establish DubboUserService Interface (common)

explain : stay jt-common It's the same project , Has been relied on by other projects , So just add Dubbo Business interface .
 Insert picture description here

1.4 reform JT-SSO For producers (sso)

1.4.1 Edit producer implementation class –DubboUserServiceImpl

explain : stay SSO Add implementation class to project , The original class does not need to be changed, just need to add a new implementation class ,mapper The interface can use the previous .
 Insert picture description here

1.4.2 Edit producer YML The configuration file

 Insert picture description here

server:
port: 8093
servlet:
context-path: /
spring:
datasource:
# introduce druid data source
#type: com.alibaba.druid.pool.DruidDataSource
#driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://127.0.0.1:3306/jtdb?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=utf8&autoReconnect=true&allowMultiQueries=true
username: root
password: root
# About Dubbo To configure
dubbo:
scan:
basePackages: com.jt # Appoint dubbo The package path of In order to scan dubbo annotation (@service), You can specify a larger range com,jt
application: # apply name
name: provider-user # An interface corresponds to a service name ( An interface can have multiple implementations , However, if the same interface is implemented, the services provided should also be the same . eg: Lao Wang Lao Li sells vegetables and implements the same interface , Lao sun sells meat under different excuses from Lao Wang and Lao Li )
registry: # Registry Center 2181 The slave is connected backup( spare ) The user gets the data from the machine The host is only responsible for monitoring the entire cluster Data synchronization , So this place should be connected to the slave instead of the host
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183
protocol: # Designated agreement name:dubbo Fixed writing
name: dubbo # Use dubbo agreement (tcp-ip) web-controller Call directly sso-Service
port: 20880 # Each service has its own specific port Can't repeat .
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
#mybatis-plush To configure
mybatis-plus:
type-aliases-package: com.jt.pojo
mapper-locations: classpath:/mybatis/mappers/*.xml configuration: map-underscore-to-camel-case: true logging: level: com.jt.mapper: debug 

1.4.3 Start producer SSO test

explain : test Dubbo Whether the service started successfully
 Insert picture description here

1.5 reform JT-Web For the consumer (web)

1.5.1 Edit consumer UserController

explain : Inject DubboService object
 Insert picture description here

1.5.2 Edit consumer YML The configuration file

server:
port: 8092
spring: # Definition springmvc view resolver
mvc:
view:
prefix: /WEB-INF/views/
suffix: .jsp
dubbo:
scan:
basePackages: com.jt
application:
name: consumer-web # Define the consumer name
registry: # Address of Registration Center
address: zookeeper://192.168.126.129:2181?backup=192.168.126.129:2182,192.168.126.129:2183

 Insert picture description here

1.5.3 Start consumer Web test

 Insert picture description here

2 User module implementation

2.1 User registration

2.1.1 URL analysis

according to url Address description request is a same domain request .
 Insert picture description here

parameter information :
 Insert picture description here

2.1.2 page JS analysis

explain :
1. According to the page url Address Find page JS The location of ctrl+h
2. Copy the rules : Copy url Writing a dead address Generally, the path in the sent request is fixed , The domain name may or may not be written , So to be safe, copy the path .
 Insert picture description here
Specific page js:
explain : According to the analysis, the returned value data information should be SysResult object .
 Insert picture description here

2.1.3 edit UserController(web project )

 Insert picture description here

package com.jt.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.pojo.User;
import com.jt.service.DubboUserService;
import com.jt.vo.SysResult;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller // Due to the design of page jump function .
@RequestMapping("/user")
public class UserController {

@Reference(timeout = 3000) // This annotation can also set the connection timeout 
private DubboUserService dubboUserService;
/** * Complete the user registration operation . * url Address : http://www.jt.com/user/doRegister * Parameters : {password:_password,username:_username,phone:_phone} * Return value : SysResult object The return is JSON strand * Business description : adopt dubbo The framework will user Information RPC Pass in jt-sso Realize the data warehousing operation . * */
@RequestMapping("/doRegister")
@ResponseBody
public SysResult saveUser(User user){

// Consumers give dubbo The agreement will user Object for remote network data transmission . Need to serialize , there use Although he didn't, he inherited it BasePojo
dubboUserService.saveUser(user);
return SysResult.success(); // In this way, there is no need to return a value 
}
}

2.1.4 edit UserService(sso)

explain : The neutral interface is common in .
 Insert picture description here

package com.jt.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
@Service(timeout =3000)
public class DubboUserServiceImpl implements DubboUserService{

@Autowired
private UserMapper userMapper;
/** * 1. The user did not deliver the email address , The mailbox temporarily uses the telephone number instead of * 2. The password needs to be encrypted md5/md5-hash * 3. Attention should be paid to transaction control in warehousing operation * @param user * @return */
@Override
@Transactional // Control things If it fails, it will not be executed ( It's OK to add it to the interface , It means that all implementation classes need transaction control )
public void saveUser(User user) {

user.setEmail(user.getPhone());// Temporarily use the phone instead of the mailbox 
//1. Get plaintext 
String password = user.getPassword();
//2. utilize Spring Tools for API Perform encryption operation md5-hash The operation of It requires bytes If you want to use salt value, you can add 
password = DigestUtils.md5DigestAsHex(password.getBytes());
user.setPassword(password);
userMapper.insert(user);
}
}

2.1.5 Start the test ( producer consumer )

 Insert picture description here

2.1.6 About POJO Description of conversion exception

When this exception occurs Dubbo Unique to the project .

Wrong statement : because SpringBoot Tools configured for hot deployment , When the code is modified , The program will restart . In the process of restarting, the program will link again zookeeper Registry Center . because zk There is a timeout in the heartbeat detection mechanism of , May be in zk There will be 2 Information as like as two peas of service providers. . ( The machine went down during another verification , When verifying the second time, Sudoku is restarted faster , So no one thinks you're down . But there was a link ZK, So there are... In the registry 2 An identical message , So when calling a service , The registry will appear 2 An identical message , Users do not know which to choose when connecting . You're going to report a mistake )
Solution : You need to restart the server manually .( Start first , Resurgent consumers )

 Insert picture description here

2.2 Introduction to the principle of single sign on

2.2.1 Requirement specification

explain : If the SESSION To achieve the user login operation , because nginx Load balancing strategy , Users can access different servers . however Session Cannot share , So users log in frequently . The user experience is not good .

explain :session Do not share , Save the data information on the server session Once the server is shut down session Will disappear , Users need to log in again . One server , The routine implementation process of password free login is generally : In the background server session Save user session information in , Then generate a voucher (eg: VIP card to the hotel ) Return to Browser client Save in cookie in , Even if the background server is turned off ( To get to the hotel, just take out your card Can be released without recognizing people ) Users can also use cookie The login operation is realized by using the voucher .

problem : If there is more than one server in the background , because nginx Load balancing strategy (nginx You can do simple load balancing , Load has little effect on several front-end servers ) Need to access different servers , and session Because they don't share ( That is, saved by different front-end servers session Different ), Therefore, when accessing another server without credentials, you need to log in again .
 Insert picture description here

How to solve the above problem? You don't need to log in again to access multiple servers ???
answer : Cannot save in session in , It should be kept in a third-party public place , And the third-party background server can access .redis Realization

 Insert picture description here

2.2.2 SSO( Single sign on ) Introduce

Single sign on (SingleSignOn,SSO), Is through the user's one-time authentication login . When the user logs in on the authentication server once , You can get access to other associated systems and applications in the single sign on system , At the same time, this implementation does not need the administrator to modify the user's login status or other information , This means that in multiple applications , Users only need to log in once to access all the mutual trust application systems . This method reduces the time consumption caused by login , Assisted user management , It's popular at present A login method

eg: After logging in to wechat, you can use official account Circle of friends And so on .

2.2.3 Jingtao project single sign on Design ( With the help of redis)

 Insert picture description here
step :
1. When the user enters user information such as user name and password and clicks register , Send the request to JT-WEB Consumer servers .
2.JT-WEB The server needs to pass user information to JT-SSO The single sign on system completes data verification .
3. If the validation fails in the single sign on system , The error message can be returned directly .
4. If the validation is successful in the single sign on system , Then the data queried by the user will be processed and saved to redis in , And produce dynamic results TICKET voucher ,( Pay attention to the timeout ).
5. after JT-SSO Pass the login credentials to JT-WEB The server .
6.JT-WEB The server will get TICKET Save the voucher information to the client Cookie in , Easy to log in next time ( Pay attention to the timeout ).

summary :
First round login , The user enters the account number in the front-end server Password and other data information , Because the front-end server cannot connect to the database, it sends the data to the background server for verification , If a value is found, the information queried by the user is transformed into json Save to redis in , And dynamically generate vouchers and return to cookie in , Login succeeded at this time . If no query is found, the error message will be returned directly .
The second round of login , First, according to cookie Voucher to Central redis Check whether there is ticket voucher , If so, implement secret free login , If not, jump to the login page and re-enter the user information to log in .

Why the same UUID without MD5 encryption , because md5 It's possible to repeat . and UUID Theoretically, it can be repeated , But in fact, the probability is very, very low .

2.3 The specific implementation of user single sign on

This module only considers the first round of login

2.3.1 User login page url analysis

explain : r=0.8989367429030823( random number ) Used to prevent browser caching .
 Insert picture description here

2.3.2 Parametric analysis

 Insert picture description here

2.3.3 page JS analysis

Empathy :ctrl+h /user/doLogin
 Insert picture description here

 $.ajax({

type: "POST",
url: "/user/doLogin?r=" + Math.random(),
contentType: "application/x-www-form-urlencoded; charset=utf-8",
data: {
username:_username,password:_password},
dataType : "json",
error: function () {

$("#nloginpwd").attr({
 "class": "text highlight2" });
$("#loginpwd_error").html(" Network timeout , Please try again later ").show().attr({
 "class": "error" });
$("#loginsubmit").removeAttr("disabled");
$this.removeAttr("disabled");
},
success: function (result) {

// If the data is not null When the 
if (result) {

var obj = eval(result);
if (obj.status == 200) {

obj.success = "http://www.jt.com";
.....

2.3.4 edit UserController(web)

View the entire domain name in the browser cookie: Take Jingdong for example . It can also be in Network View individual requests cookie

 Insert picture description here
 Insert picture description here

package com.jt.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.pojo.User;
import com.jt.service.DubboUserService;
import com.jt.vo.SysResult;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
@Controller // Due to the design of page jump function .
@RequestMapping("/user")
public class UserController {

@Reference(timeout = 3000) // This annotation can also set the connection timeout 
private DubboUserService dubboUserService;
/** * Complete the user's login operation * 1. url Address :http://www.jt.com/user/doLogin?r=0.8989367429030823 * 2. Parameters : username/password * 3. Return value : SysResult object * 4.cookie: * 4.1 setPath("/") path If you need to get cookie Data in , be url Set the path where the address is located . * url:http://www.jt.com/user/findAll * cookie.setPath("/"); Delegates can get / Next cookie All the information about , It's usually / Represents the root directory * cookie.setPath("/persion"); representative url The path of is /persion To get it cookie, Now it is url yes :/user So I can't get it cookie * 4.2 setDomain("jt.com") Set up cookie Shared range That is, as long as the suffix of the domain name is jt.com The end is cookie share * 4.3 setMaxAge(xxx) Set up cookie Survival time Company second * cookie.setMaxAge(-1); Delete... When closing a browser session * cookie.setMaxAge(0); Delete... Now cookie * cookie.setMaxAge(100); cookie The unit of time that can be stored is seconds */
@RequestMapping("/doLogin")
@ResponseBody // Change the returned result to JSON Format 
public SysResult doLogin(User user, HttpServletResponse response){

//1. Get credentials ticket If the verification is successful, the voucher has a value If the verification fails, the voucher is empty 
String ticket = dubboUserService.doLogin(user);
//2. check ticket If there is a value . Empty return fail()
if(StringUtils.isEmpty(ticket)){

// Wrong username or password 
return SysResult.fail();
}else{

//3. If the user's ticket Not for null, It indicates that the login is correct , Need to put ticket Save to cookie in 
//Cookie requirement 1.7 Days in effect 2. requirement cookie Can be in jt.com Share in your domain name 3.cookie jurisdiction 
// establish cookie object cookie The name of ( Pay attention to and js Keep consistent inside ) cookie To save values 
Cookie cookie = new Cookie("JT_TICKET",ticket);
cookie.setMaxAge(7*24*3600); // Set up cookie Survival time Unit second 
cookie.setPath("/");// Is due to cookie The effective range of 
cookie.setDomain("jt.com"); // stay jt.com Realize page domain name sharing in . It's a must for single sign on ( Our whole jt The domain name of the project has been jt.com ending )
response.addCookie(cookie); // utilize response take cookie Save to browser client .
return SysResult.success();
}
}

 Insert picture description here

2.3.5 edit UserServiceImpl(sso)

explain : The microservice architecture interface is in common in
 Insert picture description here

package com.jt.service;
import com.alibaba.dubbo.config.annotation.Service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jt.mapper.UserMapper;
import com.jt.pojo.User;
import com.jt.util.ObjectMapperUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.DigestUtils;
import redis.clients.jedis.JedisCluster;
import java.util.UUID;
@Service(timeout =3000)
public class DubboUserServiceImpl implements DubboUserService{

@Autowired
private UserMapper userMapper;
@Autowired
private JedisCluster jedisCluster;
/** * 1. Query the database according to the user name and password * 2. Verify the validity of user data . * 3. If the user's data is correct Then start the single sign on operation . * 4. If the user data is incorrect be ticket The data is null that will do . * @param user * @return */
@Override
public String doLogin(User user) {

//1. Encrypt the password ( Because the password is encrypted when registering , The same data uses the same MD5 The result of encryption is the same )
String password = DigestUtils.md5DigestAsHex(user.getPassword().getBytes());
user.setPassword(password);
// Conventional writing :
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username",user.getUsername())
.eq("password",user.getPassword());
User userDB = userMapper.selectOne(queryWrapper);
/** * Optimize the writing : If the object is passed , If the object is not null The property of serves as where Conditions * QueryWrapper<User> queryWrapper = new QueryWrapper<>(user); * User userDB = userMapper.selectOne(queryWrapper); */
/** * 2. Check whether the data is valid , Ideas : * If the object to be queried userDB by null, Check failed * If the object to be queried userDB Not for null, Check success , Then save it to redis, Generate ticket return . */
if(userDB == null){

//2.1 Wrong user name or password 
return null;
}else{

//2.2 userDB The data is not null, The user's input information is correct . Open single sign on operation .
/** * 2.2.1 Desensitization treatment : * If you directly put the query results userDB Turn into json Save to redis in , The password is exposed to others. It's not safe . * solve : Set a fake password and save it in redis in , Because the password is not stored in the database, it will not affect the database information . */
userDB.setPassword("123456 Do you believe it? ??");
String userJSON = ObjectMapperUtil.toJSON(userDB);// hold userDB Objects through encapsulated tools api Turn into json data ( user name dummy letter )
// adopt uuid Dynamic generation ticket voucher Replace horizontal lines (-) Note that "" instead of null, because uuid Generated by - Connected random string , Of course, there is no need to replace 
String ticket = UUID.randomUUID().toString().replace("-", "");
// Injection through configuration class redis Cluster object Put the data ( voucher Timeout time Query results ) Save to redis in Pay attention to setting the timeout 
jedisCluster.setex(ticket, 7*24*60*60, userJSON);
return ticket; // Return voucher 
}
}
}

2.3.6 Start producer Consumer testing (zk reids Cluster start )

explain :cookie Of value by uuid Generated credentials , Because you use an empty string instead of -, So display a continuous string .
If there is no substitute, the display format is :2da77ab6-f3a9-4d37-9d02-5f3e159b42c7
 Insert picture description here
 Insert picture description here
 Insert picture description here

2.4 User login echo

2.4.1 User information echo business description

explain : After the user logs in successfully, the request will be sent automatically , stay www.jt.com Page echo User name .
 Insert picture description here

2.4.2 page url analysis

step :
1). First After logging in successfully Jump to www.jt.com page
 Insert picture description here

2).F12 Analysis page url
explain : Click the refresh button , find Report red Request , according to url This analysis is jsonp Cross domain approach , Path splicing has cookie Proof of .
 Insert picture description here

2.4.3 page JS analysis

explain :
1.ctrl+h+ Fixed path +enter Jump to page request .
2. After logging in, the user will automatically send a request for cross domain access .
 Insert picture description here

var TT = JT = {

checkLogin : function(){

var _ticket = $.cookie("JT_TICKET");
if(!_ticket){
 // If ticket It's empty 
return ; // Program end 
}
// When dataType The type is jsonp when ,jQuery Will automatically add a... To the request link callback Parameters of 
$.ajax({

url : "http://sso.jt.com/user/query/" + _ticket,
dataType : "jsonp",
type : "GET",
success : function(data){

if(data.status == 200){

// hold json Convert string to js object 
var _data = JSON.parse(data.data);
var html =_data.username+", Welcome to Jingtao !<a href=\"http://www.jt.com/user/logout.html\" class=\"link-logout\">[ sign out ]</a>";
$("#loginbar").html(html);
}
}
});
}
}
$(function(){

// Check whether you have logged in , If you have logged in, query the login information 
TT.checkLogin();
});

2.4.4 edit JT-SSO UserController

explain : Cross domain is web Page js Send a request to sso The server , Said the control layer would be sso It says in it .
 Insert picture description here

package com.jt.controller;
import com.fasterxml.jackson.databind.util.JSONPObject;
import com.jt.pojo.User;
import com.jt.service.UserService;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import redis.clients.jedis.JedisCluster;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
@RestController
@RequestMapping("/user")// The business name should be written on the class 
public class UserController {

@Autowired
private UserService userService;
@Autowired
private JedisCluster jedisCluster;
/** * Business implementation : * 1. User pass cookie Information query user data . Because after the user logs in successfully, the data is saved in redis in , So it's actually through ticket obtain redis Business data in (k-v structure , according to k obtain v) * 2.url request : http://sso.jt.com/user/query/+ _ticket * 3. Parameters : Parameter in url in . utilize restFul obtain * 4. The return value requires : SysResult object (user Object's JSON form , stay redis What's in store is json form ) * Cross domain does not need to intercept domain names */
@RequestMapping("/query/{ticket}") //resful style 
public JSONPObject findUserByTicket(@PathVariable String ticket, HttpServletResponse response, String callback){

//1.redis Medium lru The algorithm clears the data 2. The user may delete or modify it in the browser cookie Information So we need to do if Judge whether it exists ticket
String userJSON = jedisCluster.get(ticket);// from redis In order to get ticket
if(StringUtils.isEmpty(userJSON)){

// If according to ticket Query error , Should be deleted Cookie Information (cookie A fake voucher cannot be saved and needs to be deleted eg: Go to the hotel and open a room for a fake membership card ).
Cookie cookie = new Cookie("JT_TICKET","");//value Just write a string But it can't be written null There will be problems with browser parsing 
//cookie Deleted features : Make sure it's the same as the original cookie It's the same , So add these attributes and delete them .
cookie.setDomain("jt.com");
cookie.setPath("/");
cookie.setMaxAge(0); // Delete by setting the timeout cookie API Direct deletion... Is not provided in Cookie Methods 
/** * Because the browser is based on cookie To distinguish cookie, If you send the same name to the browser twice cookie, * Sent after cookie Will overwrite the previously sent cookie. Then sent cookie Set the lifetime to zero , Therefore, the browser will delete it immediately after receiving it ! */
response.addCookie(cookie);
return new JSONPObject(callback, SysResult.fail());// This is according to jsonp Form return of .
}else{

// Return correct valid data 
return new JSONPObject(callback, SysResult.success(userJSON));
}
}
}

2.4.5 Start the test (sso web)

 Insert picture description here
If the user deletes cookie Information needs to be logged in again ,cookie Without it, you don't go to the jump of the page js 了 .
 Insert picture description here

2.5 Editing tools Api Optimize Cookie(common)

explain : Every time to get cookie Information , Will be rewritten cookie Your code is too cumbersome , So encapsulate it into a API Put in common in .

package com.jt.util;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
public class CookieUtil {

/** * This tool API The main task * 1. according to cookie The name of return valve Value * 3. newly added cookie Method * 4. Delete cookie Method */
//1. according to cookie The name of return valve Value 
// Parameters :cookie The name of request object ( save cookie adopt response object , take cookie adopt request object )
public static String getCookieValue(String cookieName, HttpServletRequest request){

// adopt request Get all... In the request cookie Array of components , No return was obtained null
Cookie[] cookies = request.getCookies();
// The user may operate the browser to delete cookie, Therefore, it is necessary to verify whether there is any in the request cookie
/** Be careful null "" empty The difference between : * eg: There is a cup on the table , There is water in the cup . * null, Means you don't even have a cup ( Not even an object ) * "" An empty string , Indicates that there is a cup and there is something in the cup , But this thing happens to be an empty string ( There are objects , The value of the object is an empty string . The empty string length is 1) * empty : Means there's nothing in the cup ( There are objects , The value of the object is null . Null value length is o) * So the array is judged not to be empty ( Valuable ), You need to first judge that there is an object and there is a value in the object . */
if(cookies !=null && cookies.length >0) {

for (Cookie cookie : cookies) {
 // because cookie No direct return specific cookie Name method, so you need to traverse 
if (cookieName.equals(cookie.getName())) {

return cookie.getValue();// according to key obtain cookie Medium value
}
}
}
return null ; // No value returned null 
}
//2. newly added You don't need to return a value 
// Parameters :cookie name value Survival time Effective range Domain name sharing redponse object 
public static void addCookie(String cookieName, String cookieValue,int maxAge,String path,String domain, HttpServletResponse response){

Cookie cookie = new Cookie(cookieName,cookieValue);
cookie.setMaxAge(maxAge);
cookie.setPath(path);
cookie.setDomain(domain);
response.addCookie(cookie);
}
//3. Delete 
/** * Parameters :cookie name value Survival time Effective range Domain name sharing redponse object * The code structure is almost the same as the new one , It's just 2 Two parameters have changed : * cookie Of value: Just pass a string / An empty string is also OK But not for null * setMaxAge Timeout time : Set to 0 * So you can directly call the new addCooKie Method , Realize code reuse . * Method to realize reuse . */
public static void deleteCookie(String cookieName, String cookieValue,int maxAge,String path,String domain, HttpServletResponse response){

// Reuse addCookie New code 
addCookie(cookieName,cookieValue,maxAge,path,domain,response);
}
}

2.5.1 Reconstruct single sign on and user login echo (3.3、3.4)

Single sign on :
 Insert picture description here
User login echo :
 Insert picture description here

2.5.2 The test again ( start-up sso web)

Echo user information after successful login
 Insert picture description here

2.6 User exit operation

2.6.1 Business description

If the user clicks exit operation , First of all, we should delete Redis Data in , Next delete Cookie Data in , Then redirect to the system home page .

2.6.2 page url analysis

step :
 Insert picture description here
Domain name is the same : Co domain request , Because of the of microservice Architecture controller stay web In the project , So the code of the control layer needs to be written in web In the project .
 Insert picture description here

2.6.3 page js analysis

explain :
1. Click exit to directly jump to the system home page , By page js Analysis shows that the request is made by < a> The tag sends a request in the normal way , The common way of request is synchronous request .(ajax Synchronization can be specified asynchronous The normal way can only be synchronous request ).
2. The synchronization request sent in the normal way jumps to the system home page again ----- Redirect (redirect).ajax Way to jump ---- On the page js Jump in call method .

 Insert picture description here

2.6.4 edit UserController(web)

Redirection instructions :
 Insert picture description here

package com.jt.controller;
import com.alibaba.dubbo.config.annotation.Reference;
import com.jt.pojo.User;
import com.jt.service.DubboUserService;
import com.jt.util.CookieUtil;
import com.jt.vo.SysResult;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import redis.clients.jedis.JedisCluster;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
@Controller
@RequestMapping("/user")
public class UserController {

@Reference(timeout = 3000) // This annotation can also set the connection timeout 
private DubboUserService dubboUserService;
@Autowired // Conduct rpc For remote calls dubbo Annotations , Use your own home, use ordinary notes 
private JedisCluster jedisCluster;
/** * Realize the user's login operation , Redirect to system home page : * url: http://www.jt.com/user/logout.html * Parameters : Temporarily no * Return value : Redirect to system home page ( So the return value type is string) * The business process : * 1. Delete Redis Data in ( adopt k Delete v,k Yes, the voucher is saved in cookie in , according to cookie The voucher in is to redis Delete in ) * 2. Delete cookie Record ( It's packaged api 了 ) */
@RequestMapping("/logout")
public String logout(HttpServletRequest request, HttpServletResponse response){

//1. according to cookie The designated name (JT_TICKET) obtain cookie Value stored inside --- voucher ticket( Tools api)
String ticket = CookieUtil.getCookieValue("JT_TICKET", request);
//2. Judge ticket Is it null ( Users operating the browser may cause cookie Delete , The return value is null, So judgment is needed )
/** * technological process :ticket If it is empty, redirect the homepage data directly ,ticket Not null delete cookie redis Then redirect the home page * Normal null judgment : If ticket by null redirect page , If it is not empty, first delete the page on the redirect home page * Judge not empty : If ticket Not empty Put the redirected page code into if You can omit a line of code outside . */
if(!StringUtils.isEmpty(ticket)){

//3. Delete redis redis Of Api Methods provided .
jedisCluster.del(ticket);
//4. Delete cookie
CookieUtil.deleteCookie("JT_TICKET","",0,"/","jt.com",response);
}
return "redirect:/";// www.jt.com/ The address is omitted "/", So redirect to the page under the system root directory , It's the home page 
}
/* Normal null judgment if(StringUtils.isEmpty(ticket)){ return "redirect:/"; }else{ jedisCluster.del(ticket); CookieUtil.deleteCookie("JT_TICKET","",0,"/","jt.com",response); return "redirect:/"; }*/
}

 Insert picture description here

2.6.5 Access test (sso web)

Click to exit , Redirect to system home page
 Insert picture description here

 Insert picture description here

copyright:author[Cool breeze AAA],Please bring the original link to reprint, thank you. https://en.javamana.com/2022/02/202202130742198621.html