master
barney 1 year ago
commit 8dfd76084d
  1. 8
      .idea/.gitignore
  2. 26
      .idea/compiler.xml
  3. 11
      .idea/encodings.xml
  4. 8
      .idea/inspectionProfiles/Project_Default.xml
  5. 20
      .idea/jarRepositories.xml
  6. 14
      .idea/misc.xml
  7. 124
      .idea/uiDesigner.xml
  8. 41
      README.md
  9. 57
      pom.xml
  10. 20
      sso-cart/pom.xml
  11. 23
      sso-cart/src/main/java/cc/bnblogs/CartApplication.java
  12. 43
      sso-cart/src/main/java/cc/bnblogs/controller/ViewController.java
  13. 2
      sso-cart/src/main/resources/application.yml
  14. 18
      sso-cart/src/main/resources/templates/index.html
  15. 2
      sso-cart/target/classes/application.yml
  16. BIN
      sso-cart/target/classes/cc/bnblogs/CartApplication.class
  17. BIN
      sso-cart/target/classes/cc/bnblogs/controller/ViewController.class
  18. 18
      sso-cart/target/classes/templates/index.html
  19. 20
      sso-login/pom.xml
  20. 23
      sso-login/src/main/java/cc/bnblogs/LoginApplication.java
  21. 83
      sso-login/src/main/java/cc/bnblogs/controller/LoginController.java
  22. 59
      sso-login/src/main/java/cc/bnblogs/controller/ViewController.java
  23. 23
      sso-login/src/main/java/cc/bnblogs/pojo/User.java
  24. 15
      sso-login/src/main/java/cc/bnblogs/utils/LoginCacheUtils.java
  25. 2
      sso-login/src/main/resources/application.yml
  26. 23
      sso-login/src/main/resources/templates/login.html
  27. 2
      sso-login/target/classes/application.yml
  28. BIN
      sso-login/target/classes/cc/bnblogs/LoginApplication.class
  29. BIN
      sso-login/target/classes/cc/bnblogs/controller/LoginController.class
  30. BIN
      sso-login/target/classes/cc/bnblogs/controller/ViewController.class
  31. BIN
      sso-login/target/classes/cc/bnblogs/pojo/User.class
  32. BIN
      sso-login/target/classes/cc/bnblogs/utils/LoginCacheUtils.class
  33. 23
      sso-login/target/classes/templates/login.html
  34. 20
      sso-main/pom.xml
  35. 28
      sso-main/src/main/java/cc/bnblogs/MainApplication.java
  36. 48
      sso-main/src/main/java/cc/bnblogs/controller/ViewController.java
  37. 2
      sso-main/src/main/resources/application.yml
  38. 23
      sso-main/src/main/resources/templates/index.html
  39. 2
      sso-main/target/classes/application.yml
  40. BIN
      sso-main/target/classes/cc/bnblogs/MainApplication.class
  41. BIN
      sso-main/target/classes/cc/bnblogs/controller/ViewController.class
  42. 23
      sso-main/target/classes/templates/index.html
  43. 20
      sso-vip/pom.xml
  44. 22
      sso-vip/src/main/java/cc/bnblogs/VipApplication.java
  45. 40
      sso-vip/src/main/java/cc/bnblogs/controller/ViewController.java
  46. 2
      sso-vip/src/main/resources/application.yml
  47. 18
      sso-vip/src/main/resources/templates/index.html
  48. 2
      sso-vip/target/classes/application.yml
  49. BIN
      sso-vip/target/classes/cc/bnblogs/VipApplication.class
  50. BIN
      sso-vip/target/classes/cc/bnblogs/controller/ViewController.class
  51. 18
      sso-vip/target/classes/templates/index.html

8
.idea/.gitignore vendored

@ -0,0 +1,8 @@
# 默认忽略的文件
/shelf/
/workspace.xml
# 基于编辑器的 HTTP 客户端请求
/httpRequests/
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CompilerConfiguration">
<annotationProcessing>
<profile default="true" name="Default" enabled="true" />
<profile name="Maven default annotation processors profile" enabled="true">
<sourceOutputDir name="target/generated-sources/annotations" />
<sourceTestOutputDir name="target/generated-test-sources/test-annotations" />
<outputRelativeToContentRoot value="true" />
<module name="sso-cart" />
<module name="sso-vip" />
<module name="sso-login" />
<module name="sso-main" />
</profile>
</annotationProcessing>
</component>
<component name="JavacSettings">
<option name="ADDITIONAL_OPTIONS_OVERRIDE">
<module name="sso-cart" options="-parameters" />
<module name="sso-login" options="-parameters" />
<module name="sso-main" options="-parameters" />
<module name="sso-vip" options="-parameters" />
<module name="use-cookie-sso" options="" />
</option>
</component>
</project>

@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding">
<file url="file://$PROJECT_DIR$/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/src/main/resources" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/sso-cart/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/sso-login/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/sso-main/src/main/java" charset="UTF-8" />
<file url="file://$PROJECT_DIR$/sso-vip/src/main/java" charset="UTF-8" />
</component>
</project>

@ -0,0 +1,8 @@
<component name="InspectionProjectProfileManager">
<profile version="1.0">
<option name="myName" value="Project Default" />
<inspection_tool class="JavadocDeclaration" enabled="true" level="WARNING" enabled_by_default="true">
<option name="ADDITIONAL_TAGS" value="author:,description:,date:" />
</inspection_tool>
</profile>
</component>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="RemoteRepositoriesConfiguration">
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Maven Central repository" />
<option name="url" value="https://repo1.maven.org/maven2" />
</remote-repository>
<remote-repository>
<option name="id" value="jboss.community" />
<option name="name" value="JBoss Community repository" />
<option name="url" value="https://repository.jboss.org/nexus/content/repositories/public/" />
</remote-repository>
<remote-repository>
<option name="id" value="central" />
<option name="name" value="Central Repository" />
<option name="url" value="https://maven.aliyun.com/repository/public" />
</remote-repository>
</component>
</project>

@ -0,0 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ExternalStorageConfigurationManager" enabled="true" />
<component name="MavenProjectsManager">
<option name="originalFiles">
<list>
<option value="$PROJECT_DIR$/pom.xml" />
</list>
</option>
</component>
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="corretto-1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
</project>

@ -0,0 +1,124 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Palette2">
<group name="Swing">
<item class="com.intellij.uiDesigner.HSpacer" tooltip-text="Horizontal Spacer" icon="/com/intellij/uiDesigner/icons/hspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="1" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="com.intellij.uiDesigner.VSpacer" tooltip-text="Vertical Spacer" icon="/com/intellij/uiDesigner/icons/vspacer.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="1" anchor="0" fill="2" />
</item>
<item class="javax.swing.JPanel" icon="/com/intellij/uiDesigner/icons/panel.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3" />
</item>
<item class="javax.swing.JScrollPane" icon="/com/intellij/uiDesigner/icons/scrollPane.svg" removable="false" auto-create-binding="false" can-attach-label="true">
<default-constraints vsize-policy="7" hsize-policy="7" anchor="0" fill="3" />
</item>
<item class="javax.swing.JButton" icon="/com/intellij/uiDesigner/icons/button.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="0" fill="1" />
<initial-values>
<property name="text" value="Button" />
</initial-values>
</item>
<item class="javax.swing.JRadioButton" icon="/com/intellij/uiDesigner/icons/radioButton.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="RadioButton" />
</initial-values>
</item>
<item class="javax.swing.JCheckBox" icon="/com/intellij/uiDesigner/icons/checkBox.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="3" anchor="8" fill="0" />
<initial-values>
<property name="text" value="CheckBox" />
</initial-values>
</item>
<item class="javax.swing.JLabel" icon="/com/intellij/uiDesigner/icons/label.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="8" fill="0" />
<initial-values>
<property name="text" value="Label" />
</initial-values>
</item>
<item class="javax.swing.JTextField" icon="/com/intellij/uiDesigner/icons/textField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JPasswordField" icon="/com/intellij/uiDesigner/icons/passwordField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JFormattedTextField" icon="/com/intellij/uiDesigner/icons/formattedTextField.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1">
<preferred-size width="150" height="-1" />
</default-constraints>
</item>
<item class="javax.swing.JTextArea" icon="/com/intellij/uiDesigner/icons/textArea.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTextPane" icon="/com/intellij/uiDesigner/icons/textPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JEditorPane" icon="/com/intellij/uiDesigner/icons/editorPane.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JComboBox" icon="/com/intellij/uiDesigner/icons/comboBox.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="2" anchor="8" fill="1" />
</item>
<item class="javax.swing.JTable" icon="/com/intellij/uiDesigner/icons/table.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JList" icon="/com/intellij/uiDesigner/icons/list.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="2" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTree" icon="/com/intellij/uiDesigner/icons/tree.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3">
<preferred-size width="150" height="50" />
</default-constraints>
</item>
<item class="javax.swing.JTabbedPane" icon="/com/intellij/uiDesigner/icons/tabbedPane.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSplitPane" icon="/com/intellij/uiDesigner/icons/splitPane.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="3" hsize-policy="3" anchor="0" fill="3">
<preferred-size width="200" height="200" />
</default-constraints>
</item>
<item class="javax.swing.JSpinner" icon="/com/intellij/uiDesigner/icons/spinner.svg" removable="false" auto-create-binding="true" can-attach-label="true">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSlider" icon="/com/intellij/uiDesigner/icons/slider.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="8" fill="1" />
</item>
<item class="javax.swing.JSeparator" icon="/com/intellij/uiDesigner/icons/separator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="6" anchor="0" fill="3" />
</item>
<item class="javax.swing.JProgressBar" icon="/com/intellij/uiDesigner/icons/progressbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1" />
</item>
<item class="javax.swing.JToolBar" icon="/com/intellij/uiDesigner/icons/toolbar.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="6" anchor="0" fill="1">
<preferred-size width="-1" height="20" />
</default-constraints>
</item>
<item class="javax.swing.JToolBar$Separator" icon="/com/intellij/uiDesigner/icons/toolbarSeparator.svg" removable="false" auto-create-binding="false" can-attach-label="false">
<default-constraints vsize-policy="0" hsize-policy="0" anchor="0" fill="1" />
</item>
<item class="javax.swing.JScrollBar" icon="/com/intellij/uiDesigner/icons/scrollbar.svg" removable="false" auto-create-binding="true" can-attach-label="false">
<default-constraints vsize-policy="6" hsize-policy="0" anchor="0" fill="2" />
</item>
</group>
</component>
</project>

@ -0,0 +1,41 @@
### 基于SpringBoot+Thymeleaf+maven实现基于Cookie的单点登录
#### 使用依赖
```xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
```
#### 四个模块
- `sso-main`: 首页
- `sso-login`: 登录
- `sso-cart`: 购物车
- `sso-vip`: `vip`系统
#### 接口
| 接口类型 | 接口地址 |
| --------- | -------------------------------------------- |
| 首页 | `http://www.codeshop.com:8082/view/index` |
| 登录 | `http://login.codeshop.com:8081/view/login` |
| 登出 | `http://login.codeshop.com:8081/view/logout` |
| 购物车 | `http://cart.codeshop.com:8080/view/index` |
| `vip`系统 | `http://vip.codeshop.com:8083/view/index` |
#### 单点登录
三个服务: 首页、购物车、`vip`系统,有一个成功登录,则所有服务均成功登录,一个退出登录,所有的服务均需重新登录

@ -0,0 +1,57 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>cc.bnblogs</groupId>
<artifactId>use-cookie-sso</artifactId>
<version>1.0-SNAPSHOT</version>
<packaging>pom</packaging>
<modules>
<module>sso-main</module>
<module>sso-cart</module>
<module>sso-vip</module>
<module>sso-login</module>
</modules>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<relativePath/>
<version>2.7.9</version>
</parent>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<scope>runtime</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
</dependencies>
</project>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cc.bnblogs</groupId>
<artifactId>use-cookie-sso</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>sso-cart</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

@ -0,0 +1,23 @@
package cc.bnblogs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @description: 购物车子模块
* @author: zfp@bnblogs.cc
* @date: 2023/3/12 15:37
*/
@SpringBootApplication
public class CartApplication {
public static void main(String[] args) {
SpringApplication.run(CartApplication.class,args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

@ -0,0 +1,43 @@
package cc.bnblogs.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import java.util.Map;
/**
* @description: 购物车页面
* @author: zfp@bnblogs.cc
* @date: 2023/3/12 16:16
*/
@Controller
@RequestMapping("/view")
public class ViewController {
@Autowired
private RestTemplate restTemplate;
private final String LOGIN_INFO_ADDR = "http://login.codeshop.com:8081/login/info?token=";
@GetMapping("/index")
public String toIndex(@CookieValue(required = false,value = "TOKEN")Cookie cookie,
HttpSession httpSession) {
if (cookie!=null) {
String token = cookie.getValue();
if(!StringUtils.isEmpty(token)) {
// 访问/login/info接口时带上token请求登录用户信息
Map result = restTemplate.getForObject(LOGIN_INFO_ADDR + token, Map.class);
// 打印已登录用户信息
// System.out.println(result);
httpSession.setAttribute("loginUser",result);
}
}
return "index";
}
}

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>购物车</title>
</head>
<body>
<h1>这里是购物车</h1>
<p th:unless="${session.loginUser==null}">
<span style="color: deepskyblue;" th:text="${session.loginUser.username}"></span> 已登录
</p>
<span>
<a th:if="${session.loginUser==null}" href="http://login.codeshop.com:8081/view/login?target=http://cart.codeshop.com:8080/view/index">登录</a>
<a th:unless="${session.loginUser==null}" href="http://login.codeshop.com:8081/view/logout?target=http://cart.codeshop.com:8080/view/index">退出</a>
</span>
</body>
</html>

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>购物车</title>
</head>
<body>
<h1>这里是购物车</h1>
<p th:unless="${session.loginUser==null}">
<span style="color: deepskyblue;" th:text="${session.loginUser.username}"></span> 已登录
</p>
<span>
<a th:if="${session.loginUser==null}" href="http://login.codeshop.com:8081/view/login?target=http://cart.codeshop.com:8080/view/index">登录</a>
<a th:unless="${session.loginUser==null}" href="http://login.codeshop.com:8081/view/logout?target=http://cart.codeshop.com:8080/view/index">退出</a>
</span>
</body>
</html>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cc.bnblogs</groupId>
<artifactId>use-cookie-sso</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>sso-login</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

@ -0,0 +1,23 @@
package cc.bnblogs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @description: 登录子模块
* @author: zfp@bnblogs.cc
* @date: 2023/3/12 15:38
*/
@SpringBootApplication
public class LoginApplication {
public static void main(String[] args) {
SpringApplication.run(LoginApplication.class,args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

@ -0,0 +1,83 @@
package cc.bnblogs.controller;
import cc.bnblogs.pojo.User;
import cc.bnblogs.utils.LoginCacheUtils;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.*;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.util.*;
/**
* @description: 用户登录逻辑
* @author: zfp@bnblogs.cc
* @date: 2023/3/12 15:53
*/
@Controller
@RequestMapping("/login")
public class LoginController {
// 模拟用户数据
private static Set<User> dbUsers;
static {
dbUsers = new HashSet<>();
dbUsers.add(new User(1,"user1","123456"));
dbUsers.add(new User(2,"user2","123456"));
dbUsers.add(new User(3,"user3","123456"));
dbUsers.add(new User(4,"user4","123456"));
dbUsers.add(new User(5,"user5","123456"));
dbUsers.add(new User(6,"user6","123456"));
}
@PostMapping
public String doLogin(User user, HttpSession httpSession, HttpServletResponse httpServletResponse) {
String target = (String) httpSession.getAttribute("target");
// 模拟数据库根据用户名和密码查询该用户是否存在
Optional<User> first = dbUsers.stream().filter(dbUser -> dbUser.getUsername().equals(user.getUsername()) &&
dbUser.getPassword().equals(user.getPassword())).findFirst();
// 如果该用户存在
if (first.isPresent()) {
// 保存用户登录信息
// 生成一个token作为key
String token = UUID.randomUUID().toString();
// 将token存入cookie
Cookie cookie = new Cookie("TOKEN",token);
// 设置相同的域
cookie.setDomain("codeshop.com");
// 将cookie通过响应返回
httpServletResponse.addCookie(cookie);
LoginCacheUtils.loginUser.put(token,first.get());
}
else {
// 返回登录失败界面,可选择重新登录
httpSession.setAttribute("msg","用户名或密码错误");
return "login";
}
// 重定向到登录前的地址
return "redirect:" + target;
}
/**
* 根据请求中的token决定是否返回用户数据
* @param token 请求方提供访问数据的token
* @return 返回响应结果
*/
@GetMapping("info")
@ResponseBody
public ResponseEntity<User> getUserInfo(String token) {
if (!StringUtils.isEmpty(token)) {
User user = LoginCacheUtils.loginUser.get(token);
return ResponseEntity.ok(user);
} else {
return new ResponseEntity<>(null, HttpStatus.BAD_REQUEST);
}
}
}

@ -0,0 +1,59 @@
package cc.bnblogs.controller;
import cc.bnblogs.pojo.User;
import cc.bnblogs.utils.LoginCacheUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
/**
* @description: 页面跳转逻辑
* @author: zfp@bnblogs.cc
* @date: 2023/3/12 15:55
*/
@Controller
@RequestMapping("/view")
public class ViewController {
@GetMapping("/login")
public String toLogin(@RequestParam(required = false,defaultValue = "") String target,
HttpSession httpSession,
@CookieValue(required = false, value = "TOKEN") Cookie cookie) {
if (StringUtils.isEmpty(target)) {
target = "http://www.codeshop.com:8082/view/index/";
}
// 如果用户已经成功登录,则不需要重复登录,直接重定向到页面
// 从token中获取到用户信息
if (cookie!=null) {
String token = cookie.getValue();
User user = LoginCacheUtils.loginUser.get(token);
if (user != null) {
return "redirect:" + target;
}
}
// todo: 注意这里没有做地址校验
httpSession.setAttribute("target",target);
return "login";
}
/**
*退出账户将cookie设置为已过期
*删除已登录的用户
*/
@GetMapping("/logout")
public String loginOut(@CookieValue(value = "TOKEN") Cookie cookie, HttpServletResponse response, String target) {
cookie.setMaxAge(0);
LoginCacheUtils.loginUser.remove(cookie.getValue());
response.addCookie(cookie);
return "redirect:" + target;
}
}

@ -0,0 +1,23 @@
package cc.bnblogs.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
/**
* @description: 用户实体
* @author: zfp@bnblogs.cc
* @date: 2023/3/12 15:51
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
// 使用链式调用
@Accessors(chain = true)
public class User {
private Integer id;
private String username;
private String password;
}

@ -0,0 +1,15 @@
package cc.bnblogs.utils;
import cc.bnblogs.pojo.User;
import java.util.HashMap;
import java.util.Map;
/**
* @description:
* @author: zfp@bnblogs.cc
* @date: 2023/3/12 17:42
*/
public class LoginCacheUtils {
public static Map<String, User> loginUser = new HashMap<>();
}

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页</title>
<style>
button {
margin-left: 5px;
}
</style>
</head>
<body>
<h2>欢迎来到登录页面</h2>
<form action="/login" method="post">
<div style="padding-bottom: 20px">用户名: <input name="username" value=""></div>
<div style="padding-bottom: 20px">密码: <input name="password" value=""></div>
<button type="submit">登录</button>
</form>
<p style="color: red;font-weight: bold" th:text="${{session.msg}}"></p>
</body>
</html>

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页</title>
<style>
button {
margin-left: 5px;
}
</style>
</head>
<body>
<h2>欢迎来到登录页面</h2>
<form action="/login" method="post">
<div style="padding-bottom: 20px">用户名: <input name="username" value=""></div>
<div style="padding-bottom: 20px">密码: <input name="password" value=""></div>
<button type="submit">登录</button>
</form>
<p style="color: red;font-weight: bold" th:text="${{session.msg}}"></p>
</body>
</html>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cc.bnblogs</groupId>
<artifactId>use-cookie-sso</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>sso-main</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

@ -0,0 +1,28 @@
package cc.bnblogs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @description: 网站首页
* @author: zfp@bnblogs.cc
* @date: 2023/3/12 15:40
*/
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class,args);
}
/**
* RestTemplate是由Spring框架提供的一个可用于应用中调用rest服务的类它简化了与http服务的通信方式
* 需要手动将RestTemplate注入到Bean容器中
* @return
*/
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

@ -0,0 +1,48 @@
package cc.bnblogs.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import java.util.Map;
/**
* @description: 网站主页
* @author: zfp@bnblogs.cc
* @date: 2023/3/12 16:12
*/
@Controller
@RequestMapping("/view")
public class ViewController {
@Autowired
private RestTemplate restTemplate;
private final String LOGIN_INFO_ADDR = "http://login.codeshop.com:8081/login/info?token=";
@GetMapping("/index")
/**
* 跳转到index.html
* 没有登录的时候没有cookie值所以required要设为false
*/
public String toIndex(@CookieValue(required = false,value = "TOKEN")Cookie cookie,
HttpSession httpSession) {
if (cookie != null) {
String token = cookie.getValue();
if (!StringUtils.isEmpty(token)) {
// 访问/login/info接口时带上token请求登录用户信息
Map result = restTemplate.getForObject(LOGIN_INFO_ADDR + token,
Map.class);
// 保存登录用户
httpSession.setAttribute("loginUser",result);
}
}
return "index";
}
}

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>欢迎来到codeshop首页</h1>
<p th:unless="${session.loginUser==null}">
<span style="color: deepskyblue;" th:text="${session.loginUser.username}"></span> 已登录
</p>
<span>
<a th:if="${session.loginUser==null}" href="http://login.codeshop.com:8081/view/login?target=http://www.codeshop.com:8082/view/index">登录</a>
<a th:unless="${session.loginUser==null}" href="http://login.codeshop.com:8081/view/logout?target=http://www.codeshop.com:8082/view/index">退出</a>
</span>
</body>
</html>

@ -0,0 +1,23 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>首页</title>
</head>
<body>
<h1>欢迎来到codeshop首页</h1>
<p th:unless="${session.loginUser==null}">
<span style="color: deepskyblue;" th:text="${session.loginUser.username}"></span> 已登录
</p>
<span>
<a th:if="${session.loginUser==null}" href="http://login.codeshop.com:8081/view/login?target=http://www.codeshop.com:8082/view/index">登录</a>
<a th:unless="${session.loginUser==null}" href="http://login.codeshop.com:8081/view/logout?target=http://www.codeshop.com:8082/view/index">退出</a>
</span>
</body>
</html>

@ -0,0 +1,20 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>cc.bnblogs</groupId>
<artifactId>use-cookie-sso</artifactId>
<version>1.0-SNAPSHOT</version>
</parent>
<artifactId>sso-vip</artifactId>
<properties>
<maven.compiler.source>8</maven.compiler.source>
<maven.compiler.target>8</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
</project>

@ -0,0 +1,22 @@
package cc.bnblogs;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;
/**
* @description:
* @author: zfp@bnblogs.cc
* @date: 2023/3/12 15:42
*/
@SpringBootApplication
public class VipApplication {
public static void main(String[] args) {
SpringApplication.run(VipApplication.class,args);
}
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

@ -0,0 +1,40 @@
package cc.bnblogs.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.CookieValue;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.client.RestTemplate;
import org.thymeleaf.util.StringUtils;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpSession;
import java.util.Map;
/**
* @description:
* @author: zfp@bnblogs.cc
* @date: 2023/3/12 16:17
*/
@Controller
@RequestMapping("/view")
public class ViewController {
@Autowired
private RestTemplate restTemplate;
private final String LOGIN_INFO_ADDR = "http://login.codeshop.com:8081/login/info?token=";
@GetMapping("/index")
public String toIndex(@CookieValue(required = false,value = "TOKEN")Cookie cookie,
HttpSession httpSession) {
if (cookie != null) {
String token = cookie.getValue();
if (!StringUtils.isEmpty(token)) {
Map result = restTemplate.getForObject(LOGIN_INFO_ADDR + token, Map.class);
httpSession.setAttribute("loginUser",result);
}
}
return "index";
}
}

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vip系统</title>
</head>
<body>
<h1>这里是Vip系统</h1>
<p th:unless="${session.loginUser==null}">
<span style="color: deepskyblue;" th:text="${session.loginUser.username}"></span> 已登录
</p>
<span>
<a th:if="${session.loginUser==null}" href="http://login.codeshop.com:8081/view/login?target=http://vip.codeshop.com:8083/view/index">登录</a>
<a th:unless="${session.loginUser==null}" href="http://login.codeshop.com:8081/view/logout?target=http://vip.codeshop.com:8083/view/index">退出</a>
</span>
</body>
</html>

@ -0,0 +1,18 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>vip系统</title>
</head>
<body>
<h1>这里是Vip系统</h1>
<p th:unless="${session.loginUser==null}">
<span style="color: deepskyblue;" th:text="${session.loginUser.username}"></span> 已登录
</p>
<span>
<a th:if="${session.loginUser==null}" href="http://login.codeshop.com:8081/view/login?target=http://vip.codeshop.com:8083/view/index">登录</a>
<a th:unless="${session.loginUser==null}" href="http://login.codeshop.com:8081/view/logout?target=http://vip.codeshop.com:8083/view/index">退出</a>
</span>
</body>
</html>
Loading…
Cancel
Save