【Spring Security】springboot + mybatis-plus + mysql 用户logout登出后token失效

在这里插入图片描述

前言

回顾:

【Spring Security】springboot + mybatis-plus + mysql 从数据库读取用户信息验证登录

【Spring Security】springboot + mybatis-plus + mysql 密码加密存储下的数据库用户验证登录

【Spring Security】springboot + mybatis-plus + mysql 用户token验证登录功能

如果使用过spring security的原生/logout接口,可以发现,如果持有之前生效过的token,即使调用/logout的用户登出了,我们还是可以访问需要权限才能调用的其他接口,这是不合理的,用户登出了怎么还可以访问其他接口呢?

因此需要手动试/logout接口调用后能够让用户权限失效,我这里利用了 enabled 字段来控制用户权限。

核心

核心是,令enabled字段成为用户登录的状态字段,当用户login登录时,修改数据表中的用户的enabled字段为true,表示登录状态。

当用户logout登出时,或者token过期时,修改数据表中的用户的enabled字段为false,表示用户已经登出。

@Component
public class UsernamePasswordLogoutSuccessHandler implements LogoutSuccessHandler {

    @Autowired
    private UserService userService;

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        Object principal = authentication.getPrincipal();
        // 获取当前登录用户名
        UserDetails userDetails = (UserDetails) principal;
        String username = userDetails.getUsername();
        // 用户失效
        userService.userDisenabled(username);

        // 构造一个 UserPattern 返回体返回
        UserPattern userPattern = new UserPattern();
        userPattern.setUsername(username);
        userPattern.setPassword(userDetails.getPassword());
        userPattern.setEnabled(Boolean.FALSE);
        userPattern.setAccountNonExpired(userDetails.isAccountNonExpired());
        userPattern.setAccountNonLocked(userDetails.isAccountNonLocked());
        userPattern.setCredentialsNonExpired(userDetails.isCredentialsNonExpired());

        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write(JSON.toJSONString(userPattern));
        out.flush();
        out.close();
    }
}

由于所有的接口调用都需要通过过滤器进行token鉴定,因此在在JWT过滤器中,增加一个对当前登录用户的判断,如果当前登录用户是enabled=true,则可以继续验证token,如果enabled=false,说明用户已经失效,直接清空token后返回。

@Slf4j
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    private String tokenHead = "Bearer ";

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private UserService userService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String tokenValue = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (!StringUtils.hasText(tokenValue)){
            filterChain.doFilter(request, response);
            return;
        }
        // 去掉tokenHead留下token
        String token = tokenValue.substring(tokenHead.length());
        Map<String, Object> parseJWT = JWTUtil.parseToken(token);

        // 检查token过期时间
        if (JWTUtil.isExpiresIn((long) parseJWT.get("expiresIn"))){
            // token 已经过期,令token 销毁,账号失效
            SecurityContextHolder.getContext().setAuthentication(null);
            filterChain.doFilter(request, response);
            return;
        }

        String username = (String) parseJWT.get("username");
        // 检查 user 是否 enabled
        if (!userService.isUserEnabled(username)) {
            // 用户不可用,token销毁
            SecurityContextHolder.getContext().setAuthentication(null);
            filterChain.doFilter(request, response);
            return;
        }

        if (StringUtils.hasText(username) && SecurityContextHolder.getContext().getAuthentication() == null){
            // 正常用户
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            if(userDetails != null && userDetails.isEnabled()){
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                // 设置用户登录状态
                log.info("authenticated user {}, setting security context", username);
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        filterChain.doFilter(request, response);
    }
}

实现

UserService.java

package org.sample.service;

import com.baomidou.mybatisplus.extension.service.IService;
import org.sample.common.request.UserRegisterRequest;
import org.sample.common.response.Response;
import org.sample.dao.entity.UserPattern;

import java.util.List;

/**
 * 用户信息服务接口
 * @author 
 */
public interface UserService extends IService<UserPattern> {

    Response userRegister(UserRegisterRequest userRegisterRequest);

    UserPattern loadByUserName(String username);

    String isAuthorizedUsersExist(List<String> authorizedUsers);

    Response userDisenabled(String username);

    Boolean isUserEnabled(String username);
}

UserServiceImpl.java

package org.sample.service.Impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.sample.common.enums.IsDeletedEnum;
import org.sample.common.request.UserRegisterRequest;
import org.sample.common.response.Response;
import org.sample.common.utils.ResponseGenerator;
import org.sample.common.utils.SecurityUtils;
import org.sample.dao.entity.UserPattern;
import org.sample.dao.mapper.UserServiceMapper;
import org.sample.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;

import javax.validation.Valid;
import java.sql.Timestamp;
import java.util.ArrayList;
import java.util.List;

/**
 * 
 * @author 
 */
@Service
public class UserServiceImpl extends ServiceImpl<UserServiceMapper, UserPattern> implements UserService, UserDetailsService {

    @Autowired
    private UserServiceMapper userServiceMapper;

    @Autowired
    private UserService userService;


    /**
     * 用户注册
     * @param userRegisterRequest
     * @return
     */
    @Override
    public Response userRegister(@Valid UserRegisterRequest userRegisterRequest) {
        String username = userRegisterRequest.getUsername();

        // XSS和SQL注入检查,得到过滤后用户名
        String s = SecurityUtils.cleanXSSSql(username);
        // 过滤前和过滤后进行比对
        if (!s.equals(username)) {
            return ResponseGenerator.genFailResponse("非法输入!");
        }

        // 用户名查重
        Integer repeat = userServiceMapper.selectCount(Wrappers.lambdaQuery(UserPattern.class)
                .likeRight(UserPattern::getUsername, username)
                .likeLeft(UserPattern::getUsername, username)
        );
        if (repeat > 0) {
            return ResponseGenerator.genFailResponse("用户名已存在,不可重复注册");
        }

        UserPattern userPattern = new UserPattern();
        userPattern.setUsername(username);
        // 密码加密储存
        String encodedPassword = new BCryptPasswordEncoder().encode(userRegisterRequest.getPassword());
        userPattern.setPassword(encodedPassword);
        userPattern.setEnabled(Boolean.TRUE);
        userPattern.setAccountNonExpired(Boolean.TRUE);
        userPattern.setAccountNonLocked(Boolean.TRUE);
        userPattern.setCredentialsNonExpired(Boolean.TRUE);
        userPattern.setIsDeleted(IsDeletedEnum.NO.getCode());
        userPattern.setCreateTime(new Timestamp(System.currentTimeMillis()));
        userPattern.setCreateUser(username);
        userPattern.setUpdateUser(username);

        // 用户名落库存储
        int insert = userServiceMapper.insert(userPattern);
        if (insert > 0) {
            return ResponseGenerator.genSuccessResponse(userPattern);
        }

        return ResponseGenerator.genFailResponse("网络错误!当前服务不可用,请尝试重试或联系客服");
    }

    /**
     * 方法一
     * spring security方法:auth.userDetailsService(userDetailsService())
     * @param username 用户名
     * @return UserPattern
     */
    @Override
    public UserPattern loadByUserName(String username) {

        // XSS和SQL注入检查
        String s = SecurityUtils.cleanXSSSql(username);
        if (!s.equals(username)) {
            throw new RuntimeException("非法输入!");
        }

        List<UserPattern> userPatterns = userServiceMapper.selectList(Wrappers.lambdaQuery(UserPattern.class)
                .likeLeft(UserPattern::getUsername, username)
                .likeRight(UserPattern::getUsername, username)
                .eq(UserPattern::getIsDeleted, IsDeletedEnum.NO.getCode())
        );
        UserPattern userPattern = userPatterns.get(0);
        return userPattern;
    }

    /**
     * 方法二
     * spring security方法:auth.userDetailsService(userDetailsService)
     * @param username 用户名
     * @return UserDetails
     * @throws UsernameNotFoundException
     */
    @Override
    public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

        // XSS和SQL注入检查
        String s = SecurityUtils.cleanXSSSql(username);
        if (!s.equals(username)) {
            throw new RuntimeException("非法输入!");
        }

        List<UserPattern> userPatterns = userServiceMapper.selectList(Wrappers.lambdaQuery(UserPattern.class)
                .likeLeft(UserPattern::getUsername, username)
                .likeRight(UserPattern::getUsername, username)
                .eq(UserPattern::getIsDeleted, IsDeletedEnum.NO.getCode())
        );
        try {
            // 如果get不到,就说明库里没有该用户,catch扔异常
            UserPattern userPattern = userPatterns.get(0);
            userPattern.setUpdateTime(new Timestamp(System.currentTimeMillis()));
            userPattern.setEnabled(Boolean.TRUE);
            userService.updateById(userPattern);

            // 如果查不到用户名,这里可以抛出UsernameNotFoundException异常
            // 根据username查询权限,这里假设从任意位置查到权限是auth
            List<GrantedAuthority> authorities = new ArrayList<>();
            authorities.add(new SimpleGrantedAuthority("auth"));
            return new User(userPattern.getUsername(), userPattern.getPassword(), Boolean.TRUE,
                    userPattern.isAccountNonExpired(), userPattern.isCredentialsNonExpired(), userPattern.isAccountNonLocked(), authorities);
        } catch (Exception e) {
            throw new RuntimeException("用户不存在!");
        }
    }

    /**
     * 检查输入的 authorizedUsers 在数据库是否存在
     * @param authorizedUsers 输入的授权用户
     * @return String 如果输入存在,返回空字符串
     */
    @Override
    public String isAuthorizedUsersExist(List<String> authorizedUsers) {
        String result = "";
        // 遍历授权用户列表 authorizedUsers
        for (String username : authorizedUsers) {
            List<UserPattern> userPatterns = userServiceMapper.selectList(Wrappers.lambdaQuery(UserPattern.class)
                    .likeLeft(UserPattern::getUsername, username)
                    .likeRight(UserPattern::getUsername, username)
                    .eq(UserPattern::getIsDeleted, IsDeletedEnum.NO.getCode())
            );
            try {
                // 如果get不到,就说明库里没有该用户,则authorizedUsers中包含无效输入,走catch
                UserPattern userPattern = userPatterns.get(0);
            } catch (Exception e) {
                log.error("输入的授权用户 " + username + " 无效,请重新检查!");
                result += username;
                return result;
            }
        }
        // 如果 authorizedUsers 存在,返回空字符串
        return result;
    }

    /**
     * 使用户失效
     * @param username 用户名
     * @return Response
     */
    @Override
    public Response userDisenabled(String username) {
        // 把用户取出
        List<UserPattern> userPatterns = userServiceMapper.selectList(Wrappers.lambdaQuery(UserPattern.class)
                .likeLeft(UserPattern::getUsername, username)
                .likeRight(UserPattern::getUsername, username)
                .eq(UserPattern::getIsDeleted, IsDeletedEnum.NO.getCode())
        );
        try {
            // 如果get不到,就说明库里没有该用户,catch扔异常
            UserPattern userPattern = userPatterns.get(0);
            userPattern.setUpdateTime(new Timestamp(System.currentTimeMillis()));
            // 用户失效
            userPattern.setEnabled(Boolean.FALSE);
            userService.updateById(userPattern);

            return ResponseGenerator.genSuccessResponse();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }

        return ResponseGenerator.genFailResponse("网咯错误!");
    }

    /**
     * 判断 user 是否 enabled
     * @param username
     * @return
     */
    @Override
    public Boolean isUserEnabled(String username) {
        // 把用户取出
        List<UserPattern> userPatterns = userServiceMapper.selectList(Wrappers.lambdaQuery(UserPattern.class)
                .likeLeft(UserPattern::getUsername, username)
                .likeRight(UserPattern::getUsername, username)
                .eq(UserPattern::isEnabled, Boolean.TRUE)
                .eq(UserPattern::getIsDeleted, IsDeletedEnum.NO.getCode())
        );
        // 如果userPatterns则为空,则user已失效
        if (userPatterns.isEmpty()) {
            return Boolean.FALSE;
        }
        return Boolean.TRUE;
    }
}


SecurityConfig.java


package org.sample.config;

import org.sample.config.filter.JwtAuthenticationTokenFilter;
import org.sample.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.AuthenticationEntryPoint;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;

/**
 * spring-security 配置类
 * @author 
 */
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private UserService userService;

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private AuthenticationSuccessHandler authenticationSuccessHandler;

    @Autowired
    private AuthenticationFailureHandler authenticationFailureHandler;

    @Autowired
    private AuthenticationEntryPoint authenticationEntryPoint;

    @Autowired
    private LogoutSuccessHandler logoutSuccessHandler;

    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;

    /**
     * PasswordEncoder 是密码加密接口,因为我们是循序渐进的,我这里先用无加密实例
     * @return PasswordEncoder
     */
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }

    /**
     * 实现configure(AuthenticationManagerBuilder auth)配置方法,为了图方便,我先在内存中创建默认用户harry,默认密码是123456,角色是user
     * 配置文件中的默认用户和默认密码注释掉了
     * @param auth
     * @throws Exception
     */
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userDetailsService);
    }


    /**
     * 通过HttpSecurity 对象,获取到表单登录配置对象,修改对应的用户名和密码参数名称,即可完成自定义用户名和密码参数名称
     * .antMatchers("/swagger-ui.html").permitAll() 等等是给swagger开绿灯,不用登录直接访问
     * .antMatchers("/register").permitAll() 给用户注册接口开绿灯,注册的时候不需要登录
     * @param http
     * @throws Exception
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .antMatchers("/swagger-ui.html").permitAll()
                .antMatchers("/webjars/**").permitAll()
                .antMatchers("/swagger-resources/**").permitAll()
                .antMatchers("/v2/*").permitAll()
                .antMatchers("/csrf").permitAll()
                .antMatchers("/").permitAll()
                .antMatchers("/login").permitAll()
                .antMatchers("/login.html").permitAll()
                .antMatchers("/authentication", "/login.html").permitAll()
                .antMatchers("/register").permitAll()
                .anyRequest().authenticated()
                .and()
                .formLogin()
                .successHandler(authenticationSuccessHandler)
                .failureHandler(authenticationFailureHandler)
                .permitAll()
                .and()
                .exceptionHandling()
                .authenticationEntryPoint(authenticationEntryPoint)
                .and()
                .logout()
                .logoutSuccessHandler(logoutSuccessHandler)
                .deleteCookies("JSESSIONID")
                .invalidateHttpSession(true)
                .permitAll()
                .and().csrf().disable()
        ;
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
    }

    public static void main(String[] args) {
    }
}

Spring Security的配置类:

AuthenticationSuccessHandler:认证成功处理器,用于自定义登录成功的处理逻辑。
AuthenticationFailureHandler:认证失败处理器,用于自定义登录失败的处理逻辑。
AuthenticationEntryPoint:未认证请求处理器,用于处理未经过身份验证的请求。
LogoutSuccessHandler:登出成功处理器,用于自定义登出成功的处理逻辑。
JwtAuthenticationTokenFilter:JWT(JSON Web Token)认证过滤器,用于处理JWT相关的认证逻辑。
passwordEncoder() 方法:返回一个BCryptPasswordEncoder实例,用于密码的加密和匹配。

configure(AuthenticationManagerBuilder auth) 方法:配置身份验证管理器,使用userDetailsService来加载用户信息。
configure(HttpSecurity http) 方法:配置HTTP安全规则,主要包括以下几个部分:
.authorizeRequests():定义哪些请求需要被授权。
.antMatchers():指定特定的请求路径及其访问权限。
对于Swagger相关路径、注册接口、登录接口等,允许所有用户访问(permitAll)。
对于其他任何请求,要求用户必须经过身份验证(authenticated)。
.formLogin():配置表单登录的相关设置。
.successHandler().failureHandler():分别设置登录成功和失败时的处理器。
.permitAll():允许所有用户进行登录操作。
.exceptionHandling().authenticationEntryPoint():设置未认证请求处理器。
.logout():配置登出相关设置。
.logoutSuccessHandler():设置登出成功时的处理器。
.deleteCookies().invalidateHttpSession():清理浏览器中的JSESSIONID cookie并使当前HttpSession失效。
.permitAll():允许所有用户进行登出操作。
.csrf().disable():禁用跨站请求伪造(CSRF)防护。
http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);:添加JWT认证过滤器,并将其放在UsernamePasswordAuthenticationFilter之前执行。

JwtAuthenticationTokenFilter.java

package org.sample.config.filter;

import lombok.extern.slf4j.Slf4j;
import org.sample.common.utils.JWTUtil;
import org.sample.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetailsSource;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

@Slf4j
@Component
public class JwtAuthenticationTokenFilter extends OncePerRequestFilter {

    private String tokenHead = "Bearer ";

    @Autowired
    private UserDetailsService userDetailsService;

    @Autowired
    private UserService userService;

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        String tokenValue = request.getHeader(HttpHeaders.AUTHORIZATION);
        if (!StringUtils.hasText(tokenValue)){
            filterChain.doFilter(request, response);
            return;
        }
        // 去掉tokenHead留下token
        String token = tokenValue.substring(tokenHead.length());
        Map<String, Object> parseJWT = JWTUtil.parseToken(token);
        String username = (String) parseJWT.get("username");

        // 检查token过期时间
        if (JWTUtil.isExpiresIn((Long) parseJWT.get("expiresIn"))){
            // 用户失效
            userService.disenabledUser(username);
            // token 已经过期,令token 销毁,账号失效
            SecurityContextHolder.getContext().setAuthentication(null);
            filterChain.doFilter(request, response);
            return;
        }

        // 检查 user 是否 enabled
        if (!userService.isUserEnabled(username)) {
            // 用户不可用,token销毁
            SecurityContextHolder.getContext().setAuthentication(null);
            filterChain.doFilter(request, response);
            return;
        }

        if (StringUtils.hasText(username) && SecurityContextHolder.getContext().getAuthentication() == null){
            // 正常用户
            UserDetails userDetails = userDetailsService.loadUserByUsername(username);
            if(userDetails != null && userDetails.isEnabled()){
                UsernamePasswordAuthenticationToken authentication = new UsernamePasswordAuthenticationToken(userDetails, null, userDetails.getAuthorities());

                authentication.setDetails(new WebAuthenticationDetailsSource().buildDetails(request));

                // 设置用户登录状态
                log.info("authenticated user {}, setting security context", username);
                SecurityContextHolder.getContext().setAuthentication(authentication);
            }
        }
        filterChain.doFilter(request, response);
    }
}

doFilterInternal() 方法,过滤器的主要执行方法,每当一个请求到达时,此方法会被调用,流程概要:
a. 从请求头中获取 Authorization 字段的值,即JWT令牌。
b. 如果没有找到令牌或者令牌为空,则直接传递请求到下一个过滤器或处理器。
c. 去掉令牌前缀 "Bearer ",留下实际的JWT令牌字符串。
d. JWTUtil.parseToken() 方法解析JWT令牌,得到一个包含用户信息(如username、expiresIn等)的Map。
e. 检查令牌是否已过期,如果已过期,则禁用用户(通过 userService.disenabledUser() 方法),并在安全上下文中设置认证为null。
f. 检查用户是否启用,如果未启用,则在安全上下文中设置认证为null。
g. 如果用户正常且当前安全上下文中的认证为空,则通过 userDetailsService.loadUserByUsername() 方法加载用户详细信息。
h. 如果用户详细信息不为空且用户启用,则创建一个新的 UsernamePasswordAuthenticationToken 对象,其中包含用户详细信息、权限等,并设置认证详情。
i. 将新的认证信息设置到安全上下文中,更新用户登录状态,并记录日志。
j. 最后,无论是否成功认证,都将请求传递到下一个过滤器或处理器。

UsernamePasswordLogoutSuccessHandler.java

package org.sample.handler;

import com.alibaba.fastjson.JSON;
import org.sample.dao.entity.UserPattern;
import org.sample.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;

/**
 * 
 * @author
 */
@Component
public class UsernamePasswordLogoutSuccessHandler implements LogoutSuccessHandler {

    @Autowired
    private UserService userService;

    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        Object principal = authentication.getPrincipal();
        // 获取当前登录用户名
        UserDetails userDetails = (UserDetails) principal;
        String username = userDetails.getUsername();
        // 用户失效
        userService.userDisenabled(username);

        // 构造一个 UserPattern 返回体返回
        UserPattern userPattern = new UserPattern();
        userPattern.setUsername(username);
        userPattern.setPassword(userDetails.getPassword());
        userPattern.setEnabled(Boolean.FALSE);
        userPattern.setAccountNonExpired(userDetails.isAccountNonExpired());
        userPattern.setAccountNonLocked(userDetails.isAccountNonLocked());
        userPattern.setCredentialsNonExpired(userDetails.isCredentialsNonExpired());

        response.setContentType("application/json;charset=utf-8");
        PrintWriter out = response.getWriter();
        out.write(JSON.toJSONString(userPattern));
        out.flush();
        out.close();
    }
}

UserPattern.java

package org.sample.dao.entity;

import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

import java.io.Serializable;
import java.sql.Timestamp;


/**
 * user用entity
 * @author 
 */
@Data
@EqualsAndHashCode(callSuper = false)
@NoArgsConstructor
@AllArgsConstructor
@TableName(value = "test.image_management_user")
public class UserPattern implements Serializable {

    /**
     * ID,自增,主键
     */
    @TableId(value = "id", type = IdType.AUTO)
    private Long id;

    /**
     * 用户名 userName
     */
    @TableField(value = "username")
    private String username;

    /**
     * 密码 password
     */
    @TableField(value = "passwd")
    private String password;

    @TableField(value = "enabled")
    private boolean enabled;

    @TableField(value = "account_non_expired")
    private boolean accountNonExpired;

    @TableField(value = "account_non_locked")
    private boolean accountNonLocked;

    @TableField(value = "credentials_non_expired")
    private boolean credentialsNonExpired;

    /**
     * 是否删除
     */
    @TableField(value = "is_deleted")
    private int isDeleted;

    /**
     * 创建时间
     */
    @TableField(value = "create_time")
    private Timestamp createTime;

    /**
     * 创建用户
     */
    @TableField(value = "create_user")
    private String createUser;

    /**
     * 更新时间
     */
    @TableField(value = "update_time")
    private Timestamp updateTime;

    /**
     * 更新用户
     */
    @TableField(value = "update_user")
    private String updateUser;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

锥栗

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值