Microservice 10: expansion and implementation of single sign on system

Business development description

Increase database access

First: the login user information comes from the database (user's own information and user's corresponding permission information)
Second: write the uploaded file information to the database (do it yourself)
Third: write the operation log of login operation and file upload operation to the database. (do it yourself)

Increase calls between services

First: the authentication service invokes the system service (obtaining the user and user permissions)
Second: both the authentication service and the resource service call the system service (pass the log to the system service for data persistence) - do it yourself

System service design and Implementation

The system service SCA system project is used to provide the basic data required by other services, such as user information, log information recording, etc

Create system engineering

Create an SCA system project to implement business as a sub project of 02 SCA files

Add project core dependencies

        <!--1.Database access related-->
        <!--1.1 mysql Database driven-->
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <!--1.2 mybatis plus plug-in unit-->
        <dependency>
            <groupId>com.baomidou</groupId>
            <artifactId>mybatis-plus-boot-starter</artifactId>
            <version>3.4.2</version>
        </dependency>
        <!--Service governance related-->
        <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 Service related-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

Create project profile

Add the bootstrap.yml file to the project. Its contents are as follows:

server:
  port: 8061
spring:
  application:
    name: sca-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

Create project launch

Step 1: add a startup class to the project

package com.jt;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SystemApplication {
    public static void main(String[] args) {
        SpringApplication.run(SystemApplication.class,args);
    }
}

Pojo object logic implementation

Add a project User object to encapsulate User information.

package com.jt.system.pojo;
import lombok.Data;
import java.io.Serializable;

/**
 * Encapsulate user information through this object
 */
@Data
public class User implements Serializable {
    private static final long serialVersionUID = 4831304712151465443L;
    private Long id;
    private String username;
    private String password;
    private String status;
}

Dao object logic implementation

Step 1: create a UserMapper interface and define a method to query user information based on user name and user permission information based on user id

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> {
    /**
     * Get user information based on user name
     * @param username
     * @return
     */
    @Select("select id,username,password,status " +
            "from tb_users " +
            "where username=#{username}")
    User selectUserByUsername(String username);

    /**
     * Query user permissions based on user id
     * @param userId User id
     * @return User permissions
     * Tables involved: 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);

}

Step 2: create the UserMapperTests class to unit test the business method

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);
    }
    @Test
    void testSelectUserPermissions(){
        List<String> permission=
        userMapper.selectUserPermissions(1L);
        System.out.println(permission);
    }
}

Logical implementation of Service object

Create UserService interface and its implementation, define user and user authority query logic, and the code is as follows:

Step 1: define the service interface. The code is as follows:

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);
}

Step 2: define the service interface implementation class

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) {
        return userMapper.selectUserPermissions(userId);
    }
}

Logical implementation of Controller object

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("/login/{username}")
    public User doSelectUserByUsername(
            @PathVariable("username") String username){
        return userService.selectUserByUsername(username);
    }
    @GetMapping("/permission/{userId}")
    public List<String> doSelectUserPermissions(
            @PathVariable("userId") Long userId){
        return userService.selectUserPermissions(userId);
    }
}

Start the service for access testing

Start the SCA system engineering service, open the browser and test the access of users and user authority information respectively

Application of Feign in certification service engineering

Business description

In the authentication SCA auth project, we call SCA system service to obtain login user information and user permission information

Add Feign dependency

Add the following dependencies to the SCA auth project

  <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-openfeign</artifactId>
  </dependency>

Pojo object logic implementation

package com.jt.auth.pojo;
import lombok.Data;
import java.io.Serializable;
@Data
public class User implements Serializable {
    private static final long serialVersionUID = 4831304712151465443L;
    private Long id;
    private String username;
    private String password;
    private String status;
}

Logic implementation of Feign interface

Create feign interface and realize remote call logic based on feign

@FeignClient(name = "sca-system",contextId = "remoteUserService")
public interface RemoteUserService {
       /**Define the method of querying user information based on user*/
       @GetMapping("/user/login/{username}")
       User selectUserByUsername(
               @PathVariable("username") String username);

       /**Query user permission information based on user name*/
       @GetMapping("/user/permission/{userId}")
       List<String> selectUserPermissions(
               @PathVariable("userId")Long userId);
}

Note: after the feign interface is defined, the @ EnableFeignClients annotation needs to be added to the SCA auth startup class

Call Feign interface logic

Add a call to feign interface in UserDetailServiceImpl in SCA auth project

/**
 * The acquisition and encapsulation of user information during login will be implemented in this object,
 * When you click the login button on the page, the loadUserByUsername method of this object will be called,
 * The user name entered on the page will be passed to the parameters of this method
 */
@Service
public class UserDetailsServiceImpl implements UserDetailsService {
    @Autowired
    private BCryptPasswordEncoder passwordEncoder;

    @Autowired
    private RemoteUserService remoteUserService;
    //UserDetails user encapsulates user information (authentication and permission information)
    @Override
    public UserDetails loadUserByUsername(String username)
            throws UsernameNotFoundException {
        //1. Query user information based on user name (user name, user status, password,...)
        com.jt.auth.pojo.User user=
                remoteUserService.selectUserByUsername(username);
        //2. Query user permission information (the database will be accessed later)
        List<String> permissions=
        remoteUserService.selectUserPermissions(user.getId());
        System.out.println("permissions="+permissions);
        List<GrantedAuthority> authorities =
        AuthorityUtils.createAuthorityList(//This is the permission information here. I'll talk about it later
                permissions.toArray(new String[]{}));
        //3. Encapsulate user information
        return new User(username,user.getPassword(),authorities);
    }
}

Start the service for access testing

Start the SCA auth, SCA resource, SCA resource gateway, SCA system and SCA resource UI projects, and then start the test from login

Tags: node.js Database MySQL Microservices

Posted on Wed, 29 Sep 2021 19:50:49 -0400 by MytHunter