Do not let your micro streaking service, based on micro-Spring Session & Spring Security service access control

Micro Services Architecture

  • Gateway: route user requests to the designated service, forwarding Cookie Session information contained in the distal end;
  • User services: user login authentication (Authentication), user authorization (Authority), user management (Redis Session Management)
  • Other services: user-dependent information Redis request verification interface

User - role - permission table structure design

  • Permission table
    permissions table control the individual functions of the minimum particle size, such as user management, resource management, configuration example table:
id authority description
1 ROLE_ADMIN_USER Manage all users
2 ROLE_ADMIN_RESOURCE Management of all resources
3 ROLE_A_1 Access to an interface of the ServiceA
4 ROLE_A_2 Another privilege of access to an interface ServiceA
5 ROLE_B_1 ServiceB access to certain interfaces
6 ROLE_B_2 Another privilege of access to an interface ServiceB
  • Roles - Permissions table
    custom roles, various combinations of rights, such as the Super Administrator has all rights, table structure Example:
id name authority_ids
1 Super Admin 1,2,3,4,5,6
2 A administrator 3,4
3 Administrator B 5,6
4 general user NULL
  • User - role table
    the user is bound to one or more roles, i.e., allocating the various rights, the exemplary table structure:
user_id role_id
1 1
1 4
2 2

User Service Design

Maven dependencies (all services)

 <!-- Security -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-security</artifactId>
        </dependency>

        <!-- Spring Session Redis -->
        <dependency>
            <groupId>org.springframework.session</groupId>
            <artifactId>spring-session-data-redis</artifactId>
        </dependency>

Application Configuration application.ymlexample:

# Spring Session 配置
spring.session.store-type=redis
server.servlet.session.persistent=true
server.servlet.session.timeout=7d
server.servlet.session.cookie.max-age=7d

# Redis 配置
spring.redis.host=<redis-host>
spring.redis.port=6379

# MySQL 配置
spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://<mysql-host>:3306/test
spring.datasource.username=<username>
spring.datasource.password=<passowrd>

User login authentication (authentication) and authorization (authority)

Slf4j
public class CustomAuthenticationFilter extends AbstractAuthenticationProcessingFilter {

    private final UserService userService;

    CustomAuthenticationFilter(String defaultFilterProcessesUrl, UserService userService) {
        super(new AntPathRequestMatcher(defaultFilterProcessesUrl, HttpMethod.POST.name()));
        this.userService = userService;
    }

    @Override
    public Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throws AuthenticationException {
        JSONObject requestBody = getRequestBody(request);
        String username = requestBody.getString("username");
        String password = requestBody.getString("password");
        UserDO user = userService.getByUsername(username);
        if (user != null && validateUsernameAndPassword(username, password, user)){
            // 查询用户的 authority
            List<SimpleGrantedAuthority> userAuthorities = userService.getSimpleGrantedAuthority(user.getId());
            return new UsernamePasswordAuthenticationToken(user.getId(), null, userAuthorities);
        }
        throw new AuthenticationServiceException("登录失败");
    }

    /**
     * 获取请求体
     */
    private JSONObject getRequestBody(HttpServletRequest request) throws AuthenticationException{
        try {
            StringBuilder stringBuilder = new StringBuilder();
            InputStream inputStream = request.getInputStream();
            byte[] bs = new byte[StreamUtils.BUFFER_SIZE];
            int len;
            while ((len = inputStream.read(bs)) != -1) {
                stringBuilder.append(new String(bs, 0, len));
            }
            return JSON.parseObject(stringBuilder.toString());
        } catch (IOException e) {
            log.error("get request body error.");
        }
        throw new AuthenticationServiceException(HttpRequestStatusEnum.INVALID_REQUEST.getMessage());
    }

    /**
     * 校验用户名和密码
     */
    private boolean validateUsernameAndPassword(String username, String password, UserDO user) throws AuthenticationException {
         return username == user.getUsername() && password == user.getPassword();
    }

}

@EnableWebSecurity
@AllArgsConstructor
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    private static final String LOGIN_URL = "/user/login";

    private static final String LOGOUT_URL = "/user/logout";

    private final UserService userService;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers(LOGIN_URL).permitAll()
                .anyRequest().authenticated()
                .and()
                .logout().logoutUrl(LOGOUT_URL).clearAuthentication(true).permitAll()
                .and()
                .csrf().disable();

        http.addFilterAt(bipAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class)
                .rememberMe().alwaysRemember(true);
    }

    /**
     * 自定义认证过滤器
     */
    private CustomAuthenticationFilter customAuthenticationFilter() {
        CustomAuthenticationFilter authenticationFilter = new CustomAuthenticationFilter(LOGIN_URL, userService);
        return authenticationFilter;
    }

}

Other Design Services

Application Configuration application.ymlexample:

# Spring Session 配置
spring.session.store-type=redis

# Redis 配置
spring.redis.host=<redis-host>
spring.redis.port=6379

Global Security Configuration

@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .csrf().disable();
    }

}

User authentication information acquisition

After successful login user service by the user, the user information is cached to Redis, cached information and CustomAuthenticationFilterthe attemptAuthentication()method returns the object related, as it is, the object returned is new UsernamePasswordAuthenticationToken(user.getId(), null, userAuthorities)that Redis caching the user's ID and the user's authority (authorities).

UsernamePasswordAuthenticationToken The first argument to the constructor is Object object, the object can be custom cache.

Obtaining the information of the user service in the micro modules as follows:

@GetMapping()
    public WebResponse test(@AuthenticationPrincipal UsernamePasswordAuthenticationToken authenticationToken){
       // 略
    }

Access control

  • Enable permissions annotation-based approach
@SpringBootApplication
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class Application {

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

}
  • Simple check permissions
    for example, delete roles interface, allowing only have ROLE_ADMIN_USERuser rights to access.
/**
     * 删除角色
     */
    @PostMapping("/delete")
    @PreAuthorize("hasRole('ADMIN_USER')")
    public WebResponse deleteRole(@RequestBody RoleBean roleBean){
          // 略
    }

@PreAuthorize("hasRole('<authority>')") It can act on the micro-service modules

  • Custom permission checking
    indicated above, hasRole()is embedded Spring Security, For custom, you may use Expression-Based Access Control, Example:
/**
 * 自定义校验服务
 */
@Service
public class CustomService{

    public boolean check(UsernamePasswordAuthenticationToken authenticationToken, String extraParam){
          // 略
    }

}

/**
     * 删除角色
     */
    @PostMapping()
    @PreAuthorize("@customService.check(authentication, #userBean.username)")
    public WebResponse custom(@RequestBody UserBean userBean){
          // 略
    }

authenticationBelonging to the built-in objects, #obtain the value of the parameter

  • Dynamic modification of any user rights
    on principle, information stored in the user's permissions Redis, modify user permissions will need to operate Redis, example:
@Service
@AllArgsConstructor
public class HttpSessionService<S extends Session>  {

    private final FindByIndexNameSessionRepository<S> sessionRepository;

    /**
     * 重置用户权限
     */
    public void resetAuthorities(Long userId, List<GrantedAuthority> authorities){
        UsernamePasswordAuthenticationToken newToken = new UsernamePasswordAuthenticationToken(userId, null, authorities);
        Map<String, S> redisSessionMap = sessionRepository.findByPrincipalName(String.valueOf(userId));
        redisSessionMap.values().forEach(session -> {
            SecurityContextImpl securityContext = session.getAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY);
            securityContext.setAuthentication(newToken);
            session.setAttribute(HttpSessionSecurityContextRepository.SPRING_SECURITY_CONTEXT_KEY, securityContext);
            sessionRepository.save(session);
        });
    }

}

Modify user privileges, simply call the httpSessionService.resetAuthorities()method can, with immediate effect.

© copyright reserved by the authors, reprint please contact the author or content partners

img

the Spring Cloud Gateway - Quick Start

APM tool looking around and found SkyWalking is my true love

the Spring external configuration injected into the interior of the Boot application of static variables

The HTML into PDF new posture

the Java Docker API calls using UnixSocket

FASTJSON fatal flaw

Service Mesh - GRPC local FBI remote service

Use Thymeleaf dynamic rendering HTML

FASTJSON fatal flaw

the Spring integration log4j2日志框架the Boot 2

core Java chapter sets off point summary of the interview on Answers

framework for Java interview clearance papers set of reference points are summarized answers

the Spring Security combat dry goods: how to protect user passwords

the Spring the Boot RabbitMQ - priority queue

Original link: https: //mp.weixin.qq.com/s __biz = MzU0MDEwMjgwNA == & mid = 2247486167 & idx = 2 & sn = 76dba01d16b7147c9b1dfb7cbf2d8d28 & chksm = fb3f132ccc489a3ad2ea05314823d660c40e8af90dcd35800422899958f98b4a258d23badba8 & token = 280305379 & lang = zh_CN # rd?

This article from the blog article multiple platforms OpenWrite release!

Guess you like

Origin www.cnblogs.com/springforall/p/11762374.html