spring boot+shiro+jwt+redis無狀態(tài)自動續(xù)簽

redis工具類 http://www.reibang.com/p/1b3f33a045bf

  1. 相關(guān)依賴
<dependency>
    <groupId>org.apache.shiro</groupId>
    <artifactId>shiro-spring</artifactId>
    <version>1.4.0</version>
</dependency>
<dependency>
    <groupId>com.auth0</groupId>
    <artifactId>java-jwt</artifactId>
    <version>3.9.0</version>
</dependency>

<!-- spring data redis 依賴 -->
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>

<dependency>
    <groupId>cn.hutool</groupId>
    <artifactId>hutool-all</artifactId>
    <version>5.6.3</version>
</dependency>
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>1.2.76</version>
</dependency>
  1. yml配置jwt
jwt:
  authoritiesKey: auth
  # 密匙KEY
  secret: KeXu6IgYf7xaPe4jpw
  # HeaderKEY
  tokenHeader: Token
  # jwt過期時間 單位秒 1天后過期=86400 7天后過期=604800
  expiration: 1800
  # 放入redis過期時間 單位秒 1天后過期=86400 7天后過期=604800
  redisExpiration: 1800

獲取yml里的jwt配置信息

import lombok.Getter;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;

/**
 * JWT配置類
 */
@Getter
@Component
@ConfigurationProperties(prefix = "jwt")
public class JWTConfig {

    public static String authoritiesKey;

    /**
     * 密鑰KEY
     */
    public static String secret;
    /**
     * TokenKey
     */
    public static String tokenHeader;
    /**
     * 過期時間
     */
    public static Integer expiration;
    /**
     * redis過期時間
     */
    public static Integer redisExpiration;

    public void setAuthoritiesKey(String authoritiesKey) {
        this.authoritiesKey = authoritiesKey;
    }

    public void setSecret(String secret) {
        this.secret = secret;
    }

    public void setTokenHeader(String tokenHeader) {
        this.tokenHeader = tokenHeader;
    }

    public void setExpiration(Integer expiration) {
        this.expiration = expiration;
    }

    public void setRedisExpiration(Integer redisExpiration) {
        this.redisExpiration = redisExpiration;
    }
    
}
  1. JwtTokenUtil用于解析和生成token
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTDecodeException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.mp.generator.config.jwt.JWTConfig;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.Serializable;
import java.util.Date;
import java.util.Objects;


public class JwtTokenUtil implements Serializable {

    private static final long serialVersionUID = -5625635588908941275L;

    public static String generateToken(String username, Long current) {
        if (null == current) {
            current = System.currentTimeMillis();
        }
        Algorithm algorithm = Algorithm.HMAC256(JWTConfig.secret);
        return JWT.create()
                .withClaim(JWTConfig.authoritiesKey, username)
                .withClaim("current", current)
                .withExpiresAt(new Date(current + JWTConfig.expiration * 1000))
                .sign(algorithm);
    }

    public static String getUsername(String token) {
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim(JWTConfig.authoritiesKey).asString();
        } catch (JWTDecodeException e) {
            return null;
        }
    }

    public static String getToken() {
        String token;
        HttpServletRequest request = ((ServletRequestAttributes) Objects.requireNonNull(RequestContextHolder.getRequestAttributes())).getRequest();
        token = request.getHeader(JWTConfig.tokenHeader);
        if (StringUtils.isBlank(token)) {
            return "";
        }
        return token;
    }

    public static boolean isExpired(String token) {
        DecodedJWT jwt = JWT.decode(token);
        Date expiration = jwt.getExpiresAt();
        return expiration.before(new Date());
    }

    public static boolean verify(String token) {
        try {
            //解密
            JWTVerifier verifier = JWT.require(Algorithm.HMAC256(JWTConfig.secret)).build();
            verifier.verify(token);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    public static Long getCurrent(String token){
        try {
            DecodedJWT jwt = JWT.decode(token);
            return jwt.getClaim("current").asLong();
        }catch (Exception e){
            return null;
        }
    }
}
  1. UserToken,TokenFilter過濾器中使用利朵,傳遞token信息
import org.apache.shiro.authc.AuthenticationToken;

import java.io.Serializable;


public class UserToken implements AuthenticationToken, Serializable {

    private static final long serialVersionUID = 1841491628743017587L;

    private final String token;


    public UserToken(String token) {
        this.token = token;
    }

    @Override
    public Object getPrincipal() {
        return token;
    }

    @Override
    public Object getCredentials() {
        return token;
    }
}
  1. 實現(xiàn)過濾器TokenFilter劲蜻,判斷用戶是否登錄
import com.mp.generator.config.jwt.JWTConfig;
import com.mp.generator.constants.RedisConstant;
import com.mp.generator.utils.JwtTokenUtil;
import com.mp.generator.utils.RedisUtil;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.BasicHttpAuthenticationFilter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpStatus;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.WebApplicationContextUtils;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Objects;
import java.util.concurrent.TimeUnit;

public class TokenFilter extends BasicHttpAuthenticationFilter {
    private final Logger log = LoggerFactory.getLogger(this.getClass());

    /**
     * 如果帶有 com.token,則對 com.token 進(jìn)行檢查幅恋,否則直接通過
     */
    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        //判斷請求的請求頭是否帶上 "Token"
        if (isLoginAttempt(request, response)) {
            //如果存在,則進(jìn)入 executeLogin 方法執(zhí)行登入泵肄,檢查 com.token 是否正確
            try {
                return executeLogin(request, response);
            } catch (Exception e) {
                log.error("shiro驗證異常 {}", Arrays.asList(e.getStackTrace()));
                responseError(response, "shiro fail");
                return false;
            }
        }
        //1.如果請求頭不存在 Token捆交,則可能是執(zhí)行登陸操作或者是游客狀態(tài)訪問,無需檢查 com.token腐巢,直接返回 true
        //2.如果請求頭不存在 Token品追,并且返回false,說明走我們的過濾器時必須帶token
        return true;
    }

    /**
     * 判斷用戶是否想要登入冯丙。
     * 檢測 header 里面是否包含 JWTConfig.tokenHeader 字段
     */
    @Override
    protected boolean isLoginAttempt(ServletRequest request, ServletResponse response) {
        HttpServletRequest req = (HttpServletRequest) request;
        String token = req.getHeader(JWTConfig.tokenHeader);
        return StringUtils.isNotBlank(token);
    }

    /**
     * 執(zhí)行登陸操作
     */
    @Override
    protected boolean executeLogin(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String token = httpServletRequest.getHeader(JWTConfig.tokenHeader);
        UserToken userToken = new UserToken(token);
        try {
            Subject subject = this.getSubject(request, response);
            subject.login(userToken);
            return this.onLoginSuccess(userToken, subject, request, response);
        } catch (AuthenticationException var5) {
            return this.onLoginFailure(userToken, var5, request, response);
        }
    }

    /**
     * 對跨域提供支持
     */
    @Override
    protected boolean preHandle(ServletRequest request, ServletResponse response) throws Exception {
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        httpServletResponse.setHeader("Access-control-Allow-Origin", httpServletRequest.getHeader("Origin"));
        httpServletResponse.setHeader("Access-Control-Allow-Methods", "GET,POST,OPTIONS,PUT,DELETE");
        httpServletResponse.setHeader("Access-Control-Allow-Headers", httpServletRequest.getHeader("Access-Control-Request-Headers"));
        // 跨域時會首先發(fā)送一個option請求肉瓦,這里我們給option請求直接返回正常狀態(tài)
        if (httpServletRequest.getMethod().equals(RequestMethod.OPTIONS.name())) {
            httpServletResponse.setStatus(HttpStatus.OK.value());
            return false;
        }
        return super.preHandle(request, response);
    }

    /**
     * token錯誤
     *
     * @param request
     * @param response
     * @return
     * @throws Exception
     */
    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        try {
            String token = ((HttpServletRequest) request).getHeader(JWTConfig.tokenHeader);
            log.info("--------token過期:{}--------", token);
        } catch (Exception e) {
            log.info("--------token不存在--------");
        }
        this.sendChallenge(request, response);
        this.responseError(response, "token已過期或不存在!");
        return Boolean.FALSE;
    }

    @Override
    protected boolean onLoginSuccess(AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response) throws Exception {
        log.info("--------onLoginSuccess--------");
        String tokenPrincipal = (String) token.getPrincipal();
        if (StringUtils.isNotBlank(tokenPrincipal)) {
            if (JwtTokenUtil.verify(tokenPrincipal)) {
                return true;
            } else {
                return refreshToken(request, response);
            }
        }
        return true;
    }

    /**
     * 將非法請求跳轉(zhuǎn)到 /unauthorized/**
     */
    private void responseError(ServletResponse response, String message) {
        HttpServletResponse httpServletResponse = (HttpServletResponse) response;
        response.reset();
        httpServletResponse.setCharacterEncoding("UTF-8");
        httpServletResponse.setContentType("application/json; charset=utf-8");
        String jsonStr = "{\"result\":\"FAILURE\",\"code\":401,\"message\":\"" + message + "\"}";
        try (PrintWriter out = response.getWriter()) {
            out.append(jsonStr);
        } catch (IOException e) {
            log.error("sendChallenge error,can not resolve httpServletResponse");
        }

    }

    public <T> T getBean(Class<T> clazz, HttpServletRequest request) {
        WebApplicationContext applicationContext = WebApplicationContextUtils.getRequiredWebApplicationContext(request.getServletContext());
        return applicationContext.getBean(clazz);
    }

    // 刷新token
    private boolean refreshToken(ServletRequest request, ServletResponse response) {
        HttpServletRequest req = (HttpServletRequest) request;
        RedisUtil redisUtil = getBean(RedisUtil.class, req);
        // 獲取傳遞過來的accessToken
        String accessToken = req.getHeader(JWTConfig.tokenHeader);
        // 獲取token里面的用戶名
        String username = JwtTokenUtil.getUsername(accessToken);
        // 判斷refreshToken是否過期了,過期了那么所含的username的鍵不存在
        if (redisUtil.hasKey(RedisConstant.CACHE_PREFIX + RedisConstant.CACHE_USER_ENTER + username)) {
            // 判斷refresh的時間節(jié)點和傳遞過來的accessToken的時間節(jié)點是否一致,不一致校驗失敗
            Long current = (Long) redisUtil.getCacheObject(RedisConstant.CACHE_PREFIX + RedisConstant.CACHE_USER_ENTER + username);
            if (Objects.equals(JwtTokenUtil.getCurrent(accessToken), current)) {
                // 獲取當(dāng)前時間節(jié)點
                long currentTimeMillis = System.currentTimeMillis();
                // 生成刷新的token
                String token = JwtTokenUtil.generateToken(username, currentTimeMillis);
                // 刷新redis里面的refreshToken,過期時間是(JWTConfig.expiration + 30*60)min
                redisUtil.setCacheObject(RedisConstant.CACHE_PREFIX + RedisConstant.CACHE_USER_ENTER + username, currentTimeMillis, JWTConfig.expiration + JWTConfig.redisExpiration, TimeUnit.SECONDS);
                // 最后將刷新的AccessToken存放在Response的Header中的JWTConfig.tokenHeader字段返回
                HttpServletResponse httpServletResponse = (HttpServletResponse) response;
                httpServletResponse.setHeader(JWTConfig.tokenHeader, token);
                httpServletResponse.setHeader("Access-Control-Expose-Headers", JWTConfig.tokenHeader);
                return true;
            }
        }
        return false;
    }
}
  1. 新建ShiroConfig泞莉,添加自己的過濾規(guī)則
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.spring.LifecycleBeanPostProcessor;
import org.apache.shiro.spring.security.interceptor.AuthorizationAttributeSourceAdvisor;
import org.apache.shiro.spring.web.ShiroFilterFactoryBean;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.aop.framework.autoproxy.DefaultAdvisorAutoProxyCreator;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.servlet.Filter;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;

@Configuration
@Slf4j
public class ShiroConfig {
    /**
     * 先走 com.**.TokenFilter 洁墙,然后 com.**.TokenFilter 如果檢測到請求頭存在token,則用token 去 login戒财,走 Realm 去驗證
     */
    @Bean
    public ShiroFilterFactoryBean factory(SecurityManager securityManager) {
        ShiroFilterFactoryBean factoryBean = new ShiroFilterFactoryBean();

        // 添加自己的過濾器并且取名為token
        Map<String, Filter> filterMap = new HashMap<>();
        //設(shè)置我們自定義的Token過濾器
        filterMap.put("token", new TokenFilter());
        factoryBean.setFilters(filterMap);
        factoryBean.setSecurityManager(securityManager);
        // 設(shè)置無權(quán)限時跳轉(zhuǎn)的 url;
        factoryBean.setUnauthorizedUrl("/unauthorized/無權(quán)限");
        Map<String, String> filterRuleMap = new LinkedHashMap<>();

        filterRuleMap.put("/unauthorized/**", "anon");
        filterRuleMap.put("/api/login/**", "anon");
        filterRuleMap.put("/**", "token");
        factoryBean.setFilterChainDefinitionMap(filterRuleMap);
        return factoryBean;
    }

    /**
     * 注入 securityManager
     */
    @Bean
    public SecurityManager securityManager(UserRealm userRealm) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        // 設(shè)置自定義 realm.
        securityManager.setRealm(userRealm);

        /*
         * 關(guān)閉shiro自帶的session热监,詳情見文檔
         * http://shiro.apache.org/session-management.html#SessionManagement-StatelessApplications%28Sessionless%29
         */
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);
        return securityManager;
    }

    /**
     * 添加注解支持
     */
    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
        defaultAdvisorAutoProxyCreator.setProxyTargetClass(true);
        return defaultAdvisorAutoProxyCreator;
    }

    @Bean
    public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(SecurityManager securityManager) {
        AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
        advisor.setSecurityManager(securityManager);
        return advisor;
    }

    @Bean
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }
}
  1. UserRealm,對登錄用戶和用戶的權(quán)限進(jìn)行驗證
import cn.hutool.core.util.ObjectUtil;
import com.mp.generator.entity.SysMenu;
import com.mp.generator.entity.SysRole;
import com.mp.generator.entity.UserInfo;
import com.mp.generator.service.UserInfoService;
import com.mp.generator.utils.JwtTokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import java.util.stream.Collectors;

@Slf4j
@Component
public class UserRealm extends AuthorizingRealm {

    @Lazy
    @Autowired
    private UserInfoService userInfoService;

    /**
     * 必須重寫此方法饮寞,不然會報錯
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof UserToken;
    }

    /**
     * 授權(quán)
     * 只有當(dāng)需要檢測用戶權(quán)限的時候才會調(diào)用此方法孝扛,例如checkRole,checkPermission之類的
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {
        log.info("授權(quán)驗證->doGetAuthenticationInfo()");
        String token = principals.toString();
        String username = JwtTokenUtil.getUsername(token);
        UserInfo userInfo = userInfoService.getUserByUsername(username);
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();
        //查詢數(shù)據(jù)庫來獲取用戶的角色
        info.addRoles(userInfo.getRoleList().stream().map(SysRole::getRoleName).collect(Collectors.toSet()));
        //查詢數(shù)據(jù)庫來獲取用戶的權(quán)限
        info.addStringPermissions(userInfo.getMenuList().stream().map(SysMenu::getPermission).collect(Collectors.toSet()));
        return info;
    }

    /**
     * 身份驗證
     * 默認(rèn)使用此方法進(jìn)行用戶名正確與否驗證,錯誤拋出異常即可幽崩。
     *
     * @param authenticationToken token
     * @return SimpleAuthenticationInfo
     * @throws AuthenticationException 登錄異常
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        log.info("登錄驗證->doGetAuthenticationInfo()");
        String token = (String) authenticationToken.getCredentials();
        log.info("當(dāng)前token : {}", token);
        String username = JwtTokenUtil.getUsername(token);
        if (ObjectUtil.isNull(username)) {
            throw new AuthenticationException("登錄過期,請重新登錄!");
        }
        UserInfo userInfo = userInfoService.getUserByUsername(username);
        if (null == userInfo) {
            throw new AuthenticationException("該用戶不存在");
        }
        log.info("當(dāng)前用戶 : {}", userInfo);
        return new SimpleAuthenticationInfo(token, token, "UserRealm");
    }
}

  1. 登錄實現(xiàn)
import com.mp.generator.config.jwt.JWTConfig;
import com.mp.generator.constants.RedisConstant;
import com.mp.generator.dto.request.LoginRequest;
import com.mp.generator.entity.UserInfo;
import com.mp.generator.service.LoginService;
import com.mp.generator.service.UserInfoService;
import com.mp.generator.utils.JwtTokenUtil;
import com.mp.generator.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class LoginServiceImpl implements LoginService {

    @Autowired
    private UserInfoService userInfoService;
    @Autowired
    private RedisUtil redisUtil;

    @Override
    public String login(LoginRequest request) {
        if (StringUtils.isBlank(request.getPassword())) {
            throw new RuntimeException("請輸入密碼");
        }
        UserInfo userInfo = userInfoService.getUserInfo(request.getUserName());
        if (null == userInfo) {
            throw new RuntimeException("用戶名不存在");
        }
        String password = new SimpleHash("MD5", request.getPassword(), userInfo.getSalt(), 1024).toHex();
        if (!password.equals(userInfo.getPassword())) {
            throw new RuntimeException("密碼不正確");
        }
        long currentTimeMillis = System.currentTimeMillis();
        String token = JwtTokenUtil.generateToken(userInfo.getUserName(), currentTimeMillis);
        redisUtil.setCacheObject(RedisConstant.CACHE_PREFIX + RedisConstant.CACHE_USER_ENTER + userInfo.getUserName(), currentTimeMillis, JWTConfig.expiration + JWTConfig.redisExpiration, TimeUnit.SECONDS);
        redisUtil.deleteObject(RedisConstant.CACHE_PREFIX + RedisConstant.CACHE_USER_INFO + userInfo.getUserName());
        userInfoService.getUserByUsername(userInfo.getUserName());
        return token;
    }
}

UserInfoServiceImpl

import cn.hutool.core.util.RandomUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.mp.generator.config.jwt.JWTConfig;
import com.mp.generator.entity.SysMenu;
import com.mp.generator.entity.SysRole;
import com.mp.generator.entity.UserInfo;
import com.mp.generator.constants.RedisConstant;
import com.mp.generator.mapper.UserInfoMapper;
import com.mp.generator.service.UserInfoService;
import com.mp.generator.utils.JwtTokenUtil;
import com.mp.generator.utils.RedisUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.crypto.hash.SimpleHash;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

@Slf4j
@Service
public class UserInfoServiceImpl extends ServiceImpl<UserInfoMapper, UserInfo> implements UserInfoService {

    @Autowired
    private RedisUtil redisUtil;

    @Override
    public UserInfo getUserInfo(String username) {
        return baseMapper.selectOne(Wrappers.<UserInfo>lambdaQuery().eq(UserInfo::getUserName, username).last("LIMIT 1"));
    }

    @Override
    public UserInfo getUserByUsername(String username) {
        UserInfo userInfo = (UserInfo) redisUtil.getCacheObject(RedisConstant.CACHE_PREFIX + RedisConstant.CACHE_USER_INFO + username);
        if (null == userInfo) {
            log.info("redis緩存用戶已過期");
            userInfo = this.getUserInfo(username);
            if (null == userInfo) {
                throw new AuthenticationException("用戶不存在");
            }
            List<SysRole> roleList = this.selectSysRoleByUserId(userInfo.getId());
            List<SysMenu> menuList = this.selectSysMenuByUserId(userInfo.getId());
            menuList.add(new SysMenu().setName("添加用戶").setPermission("user:add"));
            menuList.add(new SysMenu().setName("用戶分頁").setPermission("user:page"));
            userInfo.setRoleList(roleList);
            userInfo.setMenuList(menuList);
            redisUtil.setCacheObject(RedisConstant.CACHE_PREFIX + RedisConstant.CACHE_USER_INFO + userInfo.getUserName(), userInfo, JWTConfig.expiration + JWTConfig.redisExpiration, TimeUnit.SECONDS);
        }
        return userInfo;
    }

    @Override
    public UserInfo getCurrentUserInfo() {
        return this.getCurrentUserInfo(Boolean.FALSE);
    }

    @Override
    public UserInfo getCurrentUserInfo(Boolean forceRefresh) {
        String username = JwtTokenUtil.getUsername(JwtTokenUtil.getToken());
        if (Boolean.TRUE.equals(forceRefresh)) {
            redisUtil.deleteObject(RedisConstant.CACHE_PREFIX + RedisConstant.CACHE_USER_INFO + username);
        }
        return this.getUserByUsername(username);
    }

    @Override
    public List<SysRole> selectSysRoleByUserId(Long userId) {
        // 具體根據(jù)業(yè)務(wù)實現(xiàn)
        return new ArrayList<>();
    }

    @Override
    public List<SysMenu> selectSysMenuByUserId(Long userId) {
        // 具體根據(jù)業(yè)務(wù)實現(xiàn)
        return new ArrayList<>();
    }
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末苦始,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子慌申,更是在濱河造成了極大的恐慌陌选,老刑警劉巖,帶你破解...
    沈念sama閱讀 218,122評論 6 505
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件蹄溉,死亡現(xiàn)場離奇詭異咨油,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)柒爵,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,070評論 3 395
  • 文/潘曉璐 我一進(jìn)店門役电,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人棉胀,你說我怎么就攤上這事法瑟。” “怎么了唁奢?”我有些...
    開封第一講書人閱讀 164,491評論 0 354
  • 文/不壞的土叔 我叫張陵霎挟,是天一觀的道長。 經(jīng)常有香客問我麻掸,道長酥夭,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 58,636評論 1 293
  • 正文 為了忘掉前任论笔,我火速辦了婚禮采郎,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘狂魔。我一直安慰自己,他們只是感情好淫痰,可當(dāng)我...
    茶點故事閱讀 67,676評論 6 392
  • 文/花漫 我一把揭開白布最楷。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪籽孙。 梳的紋絲不亂的頭發(fā)上烈评,一...
    開封第一講書人閱讀 51,541評論 1 305
  • 那天,我揣著相機(jī)與錄音犯建,去河邊找鬼讲冠。 笑死,一個胖子當(dāng)著我的面吹牛适瓦,可吹牛的內(nèi)容都是我干的竿开。 我是一名探鬼主播,決...
    沈念sama閱讀 40,292評論 3 418
  • 文/蒼蘭香墨 我猛地睜開眼玻熙,長吁一口氣:“原來是場噩夢啊……” “哼否彩!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起嗦随,我...
    開封第一講書人閱讀 39,211評論 0 276
  • 序言:老撾萬榮一對情侶失蹤列荔,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后枚尼,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贴浙,經(jīng)...
    沈念sama閱讀 45,655評論 1 314
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,846評論 3 336
  • 正文 我和宋清朗相戀三年署恍,在試婚紗的時候發(fā)現(xiàn)自己被綠了悬而。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 39,965評論 1 348
  • 序言:一個原本活蹦亂跳的男人離奇死亡锭汛,死狀恐怖笨奠,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情唤殴,我是刑警寧澤般婆,帶...
    沈念sama閱讀 35,684評論 5 347
  • 正文 年R本政府宣布,位于F島的核電站朵逝,受9級特大地震影響蔚袍,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜配名,卻給世界環(huán)境...
    茶點故事閱讀 41,295評論 3 329
  • 文/蒙蒙 一啤咽、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧渠脉,春花似錦宇整、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 31,894評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽霸饲。三九已至,卻和暖如春臂拓,著一層夾襖步出監(jiān)牢的瞬間厚脉,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,012評論 1 269
  • 我被黑心中介騙來泰國打工胶惰, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留傻工,地道東北人。 一個月前我還...
    沈念sama閱讀 48,126評論 3 370
  • 正文 我出身青樓孵滞,卻偏偏與公主長得像中捆,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子剃斧,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 44,914評論 2 355

推薦閱讀更多精彩內(nèi)容