微服务——单点登录系统
1. 背景
多点登录,访问每个服务都需要重新登陆
2. 概念
登录一个站点后可以免登录其他站点
3. 准备工作
3.1 项目结构
3.2 执行sql脚本
3.3 数据库表结构
3.4 sso-system子工程的依赖
<dependencies>
<!--1.数据库访问相关-->
<!--1.1 mysql 数据库驱动-->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<!--1.2 mybatis plus 插件-->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.4.2</version>
</dependency>
<!--服务治理相关-->
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--Web 服务相关-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
3.5 sso-system子工程yml文件配置
server:
port: 8061
spring:
application:
name: sso-system #服务名
cloud:
nacos:
discovery:
server-addr: localhost:8848 #服务注册发现配置
config:
server-addr: localhost:8848
file-extension: yml
datasource: #连接数据库的配置
url: jdbc:mysql:///jt-sso?serverTimezone=Asia/Shanghai&characterEncoding=utf8
username: root
password: root
logging: #配置日志级别
level:
com.jt: debug
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
3.6 测试连接
package com.jt;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.sql.DataSource;
import java.sql.Connection;
import java.sql.SQLException;
@SpringBootTest
public class DataSourceTests {
@Autowired
private DataSource dataSource;//HikariDataSource
@Test
void testGetConnection() throws SQLException {
Connection conn=
dataSource.getConnection();
System.out.println(conn);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
实现效果
4. 业务1
4.1 编辑pojo
package com.jt.system.pojo;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.io.Serializable;
@Data
@TableName("tb-users")
public class User implements Serializable {
private static final long serialVersionUID = 4831304712151465443L;
@TableId(type = IdType.AUTO)
private Long id;
private String username;
private String password;
private String status;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
4.2 编辑Dao层
package com.jt.system.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.system.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface UserMapper extends BaseMapper<User> {
@Select("select id,username,password,status " +
"from tb_users " +
"where username=#{username}")
User selectUserByUsername(String username);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
4.3 编辑测试类
package com.jt;
import com.jt.system.pojo.User;
import com.jt.system.dao.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.List;
@SpringBootTest
public class UserMapperTests {
@Autowired
private UserMapper userMapper;
@Test
void testSelectUserByUsername(){
User user =
userMapper.selectUserByUsername("admin");
System.out.println(user);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
实现效果
拓展:享元模式
…
5. 业务2基于用户id查询用户权限
5.1 sql语句
5.2 Mapper层
package com.jt.system.dao;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jt.system.pojo.User;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Select;
import java.util.List;
@Mapper
public interface UserMapper extends BaseMapper<User> {
@Select("select id,username,password,status " +
"from tb_users " +
"where username=#{username}")
User selectUserByUsername(String username);
/**
* 基于用户id查询用户权限
* @param userId 用户id
* @return 用户的权限
* 涉及到的表:tb_user_roles,tb_role_menus,tb_menus
*/
@Select("select distinct m.permission " +
"from tb_user_roles ur join tb_role_menus rm on ur.role_id=rm.role_id" +
" join tb_menus m on rm.menu_id=m.id " +
"where ur.user_id=#{userId}")
List<String> selectUserPermissions(Long userId);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
5.3 Service层
package com.jt.system.service.impl;
import com.jt.system.dao.UserMapper;
import com.jt.system.pojo.User;
import com.jt.system.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public User selectUserByUsername(String username) {
return userMapper.selectUserByUsername(username);
}
@Override
public List<String> selectUserPermissions(long userId) {
//方案一:在这里可以调用数据层的单表查询方法,查询三次获取用户信息
//方案二:调用数据层的多表嵌套或多表关联关联方法执行1次查询
return userMapper.selectUserPermissions(userId);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
package com.jt.system.service;
import com.jt.system.pojo.User;
import java.util.List;
public interface UserService {
User selectUserByUsername(String username);
List<String> selectUserPermissions(long userId);
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
5.4 Controller层
package com.jt.system.controller;
import com.jt.system.pojo.User;
import com.jt.system.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import java.util.List;
@RestController
@RequestMapping("/user")
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/selectUserByUsername/{username}")
public User selectUserByUsername(@PathVariable("username") String username){
return userService.selectUserByUsername(username);
}
@GetMapping("/selectUserPermissions/{userId}")
public List<String> selectUserPermissions(@PathVariable("userId") long userId){
return userService.selectUserPermissions(userId);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
实现效果
5.5 配置中心配置信息
6. 统一认证工程设计及实现
6.1 创建sso-auth子工程
6.2 配置pom.xml文件
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-discovery</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.cloud</groupId>
<artifactId>spring-cloud-starter-alibaba-nacos-config</artifactId>
</dependency>
<!--SSO技术方案:SpringSecurity+JWT+oauth2-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-oauth2</artifactId>
</dependency>
<!--open feign-->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
</dependencies>
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
6.3 配置bootstrap.yml文件
server:
port: 8071
spring:
application:
name: sso-auth
cloud:
nacos:
discovery:
server-addr: localhost:8848
config:
server-addr: localhost:8848
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
6.4 创建启动类
package com.jt;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class AuthApplication {
public static void main(String[] args) {
SpringApplication.run(AuthApplication.class,args);
}
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
实现效果
为spring security内置的登陆页面
访问http://localhost:8071为什么跳到了登陆页面?
因为需要认证
总结
- 单点登陆系统解决方案?数据库、token
- 为什么要设计单点登录系统??
- 工程结构???
推荐阅读