【Java】利用Token进行登录控制以及限制接口访问

2023-11-04


前言

使用Token进行登录认证功能;用户登录后获取Token,调用固定规则接口需要在请求头中传入Token才可调用接口否则提示相应异常


一、pom.xml

        <!-- cache -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-cache</artifactId>
        </dependency>
        <dependency>
            <groupId>net.sf.ehcache</groupId>
            <artifactId>ehcache</artifactId>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.apache.shiro/shiro-ehcache -->
        <dependency>
            <groupId>org.apache.shiro</groupId>
            <artifactId>shiro-ehcache</artifactId>
            <version>1.9.1</version>
        </dependency>
                <!-- jwt-->
        <dependency>
            <groupId>com.auth0</groupId>
            <artifactId>java-jwt</artifactId>
            <version>4.0.0</version>
        </dependency>
        <dependency>
            <groupId>io.jsonwebtoken</groupId>
            <artifactId>jjwt</artifactId>
            <version>0.9.1</version>
        </dependency>

二、ShiroConfig

Shiro配置代码,代码如下:

import com.example.whwechat.oauth2.OAuth2Filter;
import com.example.whwechat.oauth2.OAuth2Realm;
import net.sf.ehcache.CacheManager;
import org.apache.shiro.cache.ehcache.EhCacheManager;
import org.apache.shiro.mgt.DefaultSessionStorageEvaluator;
import org.apache.shiro.mgt.DefaultSubjectDAO;
import org.apache.shiro.mgt.SecurityManager;
import org.apache.shiro.session.mgt.SessionManager;
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.apache.shiro.web.session.mgt.DefaultWebSessionManager;
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;


/**
 * Shiro配置
 *
 * @author chenshun
 * @date 2017-04-20 18:33
 */
@Configuration
public class ShiroConfig {

    @Bean("sessionManager")
    public SessionManager sessionManager(){
        DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();
        sessionManager.setSessionValidationSchedulerEnabled(true);
        sessionManager.setSessionIdCookieEnabled(true);
        return sessionManager;
    }

    @Bean("securityManager")
    public SecurityManager securityManager(OAuth2Realm oAuth2Realm, SessionManager sessionManager, EhCacheManager cacheManager) {
        DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
        //启用身份验证缓存,即缓存AuthenticationInfo信息,默认false
        oAuth2Realm.setAuthenticationCachingEnabled(true);
        // 对应encachexml缓存配置
        oAuth2Realm.setAuthenticationCacheName("defaultCache");
        //启用授权缓存,即缓存AuthorizationInfo信息,默认false
        oAuth2Realm.setAuthorizationCachingEnabled(true);
        // 对应encachexml缓存配置
        oAuth2Realm.setAuthorizationCacheName("defaultCache");
        securityManager.setRealm(oAuth2Realm);
        securityManager.setSessionManager(sessionManager);
        securityManager.setCacheManager(cacheManager);
        //关闭shiro自带的session
        DefaultSubjectDAO subjectDAO = new DefaultSubjectDAO();
        DefaultSessionStorageEvaluator defaultSessionStorageEvaluator = new DefaultSessionStorageEvaluator();
        defaultSessionStorageEvaluator.setSessionStorageEnabled(false);
        subjectDAO.setSessionStorageEvaluator(defaultSessionStorageEvaluator);
        securityManager.setSubjectDAO(subjectDAO);
        return securityManager;
    }

    @Bean
    public EhCacheManager ehCacheManager(CacheManager cacheManager) {
        EhCacheManager em = new EhCacheManager();
        //将ehcacheManager转换成shiro包装后的ehcacheManager对象
        em.setCacheManager(cacheManager);
        em.setCacheManagerConfigFile("classpath:ehcache.xml");
        return em;
    }

    @Bean("shiroFilter")
    public ShiroFilterFactoryBean shirFilter(SecurityManager securityManager) {
        ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean();
        shiroFilter.setSecurityManager(securityManager);
        //oauth过滤
        Map<String, Filter> filters = new HashMap<>();
        filters.put("oauth2", new OAuth2Filter());
        shiroFilter.setFilters(filters);
        //注意此处使用的是LinkedHashMap,是有顺序的,shiro会按从上到下的顺序匹配验证,匹配了就不再继续验证
        //所有上面的url要苛刻,宽松的url要放在下面,尤其是"/**"要放到最下面,如果放前面的话其后的验证规则就没作用了。
        LinkedHashMap<String, String> filterChainDefinitionMap = new LinkedHashMap<>();
        filterChainDefinitionMap.put("/token", "anon");
        // 除上以外所有url前缀带有Interface都需要通过验证,否则直接访问登陆界面
        //我这里设置的是auth后缀的地址进行权限校验,也可以根据自己需求设置
        filterChainDefinitionMap.put("/auth/**", "oauth2");
        filterChainDefinitionMap.put("/", "anon");
        shiroFilter.setFilterChainDefinitionMap(filterChainDefinitionMap);
        return shiroFilter;
    }

    @Bean("lifecycleBeanPostProcessor")
    public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
        return new LifecycleBeanPostProcessor();
    }

    @Bean
    public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator() {
        DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator();
        proxyCreator.setProxyTargetClass(true);
        return proxyCreator;
    }

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

}

三、oauth2

oauth2配置类

3.1、OAuth2Filter

代码如下:

import com.alibaba.fastjson.JSONObject;
import com.example.whcommon.util.sm2.StringUtil;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.web.filter.authc.AuthenticatingFilter;
import org.springframework.web.bind.annotation.RequestMethod;

import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * oauth2过滤器
 *
 * @author Administrator
 */
public class OAuth2Filter extends AuthenticatingFilter {

    @Override
    protected AuthenticationToken createToken(ServletRequest request, ServletResponse response) throws Exception {
        //获取请求token
        String token = getRequestToken((HttpServletRequest) request);

        if (StringUtil.isEmpty(token)) {
            return null;
        }

        return new OAuth2Token(token);
    }

    @Override
    protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) {
        return ((HttpServletRequest) request).getMethod().equals(RequestMethod.OPTIONS.name());
    }

    @Override
    protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
        //获取请求token,如果token不存在,直接返回401
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        String token = getRequestToken((HttpServletRequest) request);
        if (StringUtil.isEmpty(token)) {
            HttpServletResponse httpResponse = (HttpServletResponse) response;
            httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
            httpResponse.setHeader("Access-Control-Allow-Origin", httpServletRequest.getHeader("Origin"));

            JSONObject json = new JSONObject();
            json.put("code", "401");
            json.put("message", "invalid token");

            httpResponse.getWriter().print(json);

            return false;
        }

        return executeLogin(request, response);
    }

    @Override
    protected boolean onLoginFailure(AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {
        HttpServletResponse httpResponse = (HttpServletResponse) response;
        HttpServletRequest httpServletRequest = (HttpServletRequest) request;
        httpResponse.setContentType("application/json;charset=utf-8");
        httpResponse.setHeader("Access-Control-Allow-Credentials", "true");
        httpResponse.setHeader("Access-Control-Allow-Origin", httpServletRequest.getHeader("Origin"));
        try {
            //处理登录失败的异常
            Throwable throwable = e.getCause() == null ? e : e.getCause();

            JSONObject json = new JSONObject();
            json.put("code", "401");
            json.put("message", throwable.getMessage());

            httpResponse.getWriter().print(json);
        } catch (IOException e1) {

        }

        return false;
    }

    /**
     * 获取请求的token
     */
    private String getRequestToken(HttpServletRequest httpRequest) {
        //从header中获取token
        String token = httpRequest.getHeader("token");
        //如果header中不存在token,则从参数中获取token
        if (StringUtil.isEmpty(token)) {
            token = httpRequest.getParameter("token");
        }
        return token;
    }

}

3.2、OAuth2Realm

代码如下:

import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.whwechat.dao.PermissionsDao;
import com.example.whwechat.util.TokenGenerator;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.web.mgt.DefaultWebSecurityManager;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;


/**
 * 认证
 */
@Component
public class OAuth2Realm extends AuthorizingRealm {

    //这个查用户信息的,根据自己代码修改
    @Resource
    @Lazy
    PermissionsDao permissionsDao;


    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof OAuth2Token;
    }


    /**
     * 认证(登录时调用)
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token)
            throws AuthenticationException {
        System.out.println("认证(登录时调用)");
        String accessToken = (String) token.getPrincipal();
        DecodedJWT decodedJwt = TokenGenerator.verifyManagerToken(accessToken);
        if (decodedJwt == null) {
            throw new IncorrectCredentialsException("登录已过期,请重新登录");
        }
        //TokenGenerator 这个工具类写在下面
        String code = TokenGenerator.getManagerCode(decodedJwt);
        //查询用户密码,根据实际需求修改
        String userPassword = permissionsDao.getPassword(code);
        if (userPassword == null) {
            throw new UnknownAccountException("用户不存在");
        }
        return new SimpleAuthenticationInfo(userPassword, accessToken, getName());
    }

    /**
     * 自定义方法:清除所有 授权缓存
     */
    public void clearAllCachedAuthorizationInfo() {
        getAuthorizationCache().clear();
    }

    /**
     * 自定义方法:清除所有 认证缓存
     */
    public void clearAllCachedAuthenticationInfo() {
        getAuthenticationCache().clear();
    }

    /**
     * 自定义方法:清除所有的 认证缓存 和 授权缓存
     */
    public void clearAllCache() {
        clearAllCachedAuthenticationInfo();
        clearAllCachedAuthorizationInfo();
    }

    public static void main(String[] args) {
        // 其他接口调用清除缓存demo
        DefaultWebSecurityManager securityManager =
                (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
        OAuth2Realm oAuth2Realm = (OAuth2Realm) securityManager.getRealms().iterator().next();
        oAuth2Realm.clearAllCache();
    }

    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        System.out.println("这是权限信息");
        return null;
    }

3.3、OAuth2Token

代码如下:

import org.apache.shiro.authc.AuthenticationToken;

/**
 * token
 *
 * @author Administrator
 */
public class OAuth2Token implements AuthenticationToken {

    private final String token;

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

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

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

四、Token工具类

4.1、TokenAesUtil

代码如下:


import cn.hutool.core.util.CharsetUtil;
import cn.hutool.crypto.symmetric.SymmetricAlgorithm;
import cn.hutool.crypto.symmetric.SymmetricCrypto;
import com.alibaba.fastjson.JSONObject;
import org.springframework.stereotype.Component;

import java.util.HashMap;
import java.util.Map;
import java.util.Set;

/**
 * @author wcs
 * @description token 用户信息AES加密工具类
 * @date 2021/9/1 9:46
 */
@Component
public class TokenAesUtil {

    /**
     * token用户信息AES加密密钥
     */
    private static final String AES_USER_INFO_SECRET_KEY = "dolNypS7YGV5fzZm";

    SymmetricCrypto aes;

    /**
     * 初始化AES对象
     */
    private void initAes() {
        aes = new SymmetricCrypto(SymmetricAlgorithm.AES, AES_USER_INFO_SECRET_KEY.getBytes());
    }

    /**
     * 解密只返回用户id
     *
     * @param encryptHex 加密串
     * @return 用户id
     */
    public String decryptUserId(String encryptHex) {
        String userStr = decryptStr(encryptHex);
        JSONObject jsonObject = JSONObject.parseObject(userStr);
        return jsonObject.getString("userId");
    }

    /**
     * 解密只返回用户证件号
     *
     * @param encryptHex 加密串
     * @return 用户证件号
     */
    public String decryptCertNo(String encryptHex) {
        String userStr = decryptStr(encryptHex);
        JSONObject jsonObject = JSONObject.parseObject(userStr);
        return jsonObject.getString("certNo");
    }


    /**
     * 判断用户密码强度
     *
     * @param password 用户密码
     * @return true:弱密码,false:强密码
     */
    public static Boolean isStringPwd(String password) {
        Map<String, String> map = new HashMap<String, String>();
        for (int i = 0; i < password.length(); i++) {
            int a = password.charAt(i);
            if (a >= 48 && a <= 57) {// 数字
                map.put("数字", "数字");
            } else if (a >= 65 && a <= 90) {// 大写
                map.put("大写", "大写");
            } else if (a >= 97 && a <= 122) {// 小写
                map.put("小写", "小写");
            } else {
                map.put("特殊", "特殊");
            }
        }
        Set<String> sets = map.keySet();
        int pwdSize = sets.size();// 密码字符种类数
        int pwdLength = password.length();// 密码长度
        return pwdSize < 3 || pwdLength < 8;
    }

    /**
     * 解密只返回用户真实姓名
     *
     * @param encryptHex 加密串
     * @return 用户真实姓名
     */
    public String decryptRealName(String encryptHex) {
        String userStr = decryptStr(encryptHex);
        JSONObject jsonObject = JSONObject.parseObject(userStr);
        return jsonObject.getString("realName");
    }

    /**
     * 解密只返回用户手机号
     *
     * @param encryptHex 加密串
     * @return 用户手机号
     */
    public String decryptTelephone(String encryptHex) {
        String userStr = decryptStr(encryptHex);
        JSONObject jsonObject = JSONObject.parseObject(userStr);
        return jsonObject.getString("telephone");
    }

    public String decryptHealthCard(String encryptHex) {
        String userStr = decryptStr(encryptHex);
        JSONObject jsonObject = JSONObject.parseObject(userStr);
        return jsonObject.getString("healthCard");
    }

    /**
     * 解密返回用户信息JSON
     *
     * @param encryptHex 加密串
     * @return 用户信息JSON
     */
    public JSONObject decryptUserJson(String encryptHex) {
        String userStr = decryptStr(encryptHex);
        return JSONObject.parseObject(userStr);
    }


    /**
     * @param content 需要加密的内容
     * @return 加密为16进制表示
     */
    public String encryptHex(String content) {
        if (aes == null) {
            initAes();
        }
        return aes.encryptHex(content);
    }

    /**
     * 解密
     *
     * @param encryptHex 加密串
     * @return 解密数据
     */
    public String decryptStr(String encryptHex) {
        if (aes == null) {
            initAes();
        }
        return aes.decryptStr(encryptHex, CharsetUtil.CHARSET_UTF_8);
    }
}

4.2、TokenGenerator

代码如下:

import com.alibaba.fastjson.JSONObject;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.JWTCreationException;
import com.auth0.jwt.exceptions.JWTVerificationException;
import com.auth0.jwt.interfaces.DecodedJWT;
import com.example.whcommon.util.MyStringUtil;
import com.example.whcommon.util.sm2.StringUtil;
import com.example.whwechat.exception.CustomException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import java.util.Calendar;
import java.util.Date;

/**
 * 生成token
 *
 * @author Administrator
 */
@Component
@Slf4j
public class TokenGenerator {
    @Resource
    private TokenAesUtil tokenAesUtil;

    @Resource
    protected HttpServletRequest request; // 自动注入request

    /**
     * 用户
     */
    private final int USER = 0;
    /**
     * 管理员用户
     */
    private final int MANAGER_USER = 1;
    /**
     * 亲情用户
     */
    private final int RELATIVE_USER = 2;

    public static final String JWT_SECRET = "TESTSIESST";
    private static final String JWT_ISS = "测试信息技术有限公司";
    public static final String JWT_USER_SECRET = "D2M0R2H1";
    private static int managerExpiryTime = 1;
    private static int managerExpiryTimeUnit = Calendar.HOUR;
    private static int userExpiryTime = 7;
    private static int userExpiryTimeUnit = Calendar.DATE;
    private static int relativeUserExpiryTime = 9999;
    private static int relativeUserExpiryTimeUnit = Calendar.DATE;

    /**
     * 设置token过期时间
     */
    private void setTokenExpireTime(int type, String configValue) {
        //系统Token过期时间
        String[] split = configValue.split("\\|");
        int expireTime = Integer.parseInt(split[0]);
        if (type == MANAGER_USER) {
            managerExpiryTime = expireTime;
        } else if (type == USER) {
            userExpiryTime = expireTime;
        } else {
            relativeUserExpiryTime = expireTime;
        }
        String timeUnit = split[1];
        if ("h".equalsIgnoreCase(timeUnit)) { // 小时
            if (type == MANAGER_USER) {
                managerExpiryTimeUnit = Calendar.HOUR;
            } else if (type == USER) {
                userExpiryTimeUnit = Calendar.HOUR;
            } else {
                relativeUserExpiryTimeUnit = Calendar.HOUR;
            }
        } else if ("m".equalsIgnoreCase(timeUnit)) { // 分钟
            if (type == MANAGER_USER) {
                managerExpiryTimeUnit = Calendar.MINUTE;
            } else if (type == USER) {
                userExpiryTimeUnit = Calendar.MINUTE;
            } else {
                relativeUserExpiryTimeUnit = Calendar.MINUTE;
            }
        } else { // 月
            if (type == MANAGER_USER) {
                managerExpiryTimeUnit = Calendar.DATE;
            } else if (type == USER) {
                userExpiryTimeUnit = Calendar.DATE;
            } else {
                relativeUserExpiryTimeUnit = Calendar.DATE;
            }
        }
    }

    /**
     * 获取token
     *
     * @param userName    用户名称
     * @param configValue SYSTEM_USER_TOKEN_TIME (Token过期时间) 90|d
     * @return token
     */
    public String generateManagerToken(String userName, String configValue) {
        try {
            setTokenExpireTime(MANAGER_USER, configValue);
            Algorithm algorithm = Algorithm.HMAC256(JWT_SECRET);
            Calendar calendar = Calendar.getInstance();
            Date currentDate = calendar.getTime();
            // 设置token过期时间
            calendar.add(managerExpiryTimeUnit, managerExpiryTime);
            return JWT.create()
                    .withIssuer(JWT_ISS)
                    .withExpiresAt(calendar.getTime())
                    .withClaim("userName", userName)
                    .withIssuedAt(currentDate)
                    .sign(algorithm);
        } catch (JWTCreationException exception) {
            // Invalid Signing configuration / Couldn't convert Claims.
            throw new JWTCreationException(exception.getMessage(), exception.getCause());
        }
    }


    public static DecodedJWT verifyManagerToken(String token) {
        return verifyToken(token, JWT_SECRET);
    }

    public static DecodedJWT verifyUserToken(String token) {
        // TODO 为方便开发,使用相同的密钥加密,线上环境需修改
        return verifyToken(token, JWT_SECRET);
        //return verifyToken(token, JWT_USER_SECRET);
    }

    /**
     * 校验token
     *
     * @param token token
     * @return 校验通过返回DecodedJWT信息,失败返回null
     */
    private static DecodedJWT verifyToken(String token, String secret) {
        try {
            Algorithm algorithm = Algorithm.HMAC256(secret);
            JWTVerifier verifier =
                    JWT.require(algorithm)
                            .withIssuer(JWT_ISS)
                            .build(); // Reusable verifier instance
            return verifier.verify(token);
        } catch (JWTVerificationException exception) {
            // Invalid signature/claims
            return null;
        }
    }


    /**
     * 获取用户姓名
     *
     * @return 用户姓名
     */
    public String getUserRealName() {
        String token = getRequestToken();
        String userStr = decodeUser(token);
        return tokenAesUtil.decryptRealName(userStr);
    }


    /**
     * 获取用户信息JSON
     *
     * @return JSONObject
     */
    public JSONObject getUserJson() {
        String token = getRequestToken();
        String userStr = decodeUser(token);
        return tokenAesUtil.decryptUserJson(userStr);
    }

    private String decodeUser(String token) {
        if (MyStringUtil.isEmpty(token)) {
            log.info("token为空");
            return null;
        }
        DecodedJWT jwt = verifyUserToken(token);
        if (jwt == null) {
            log.info("非法token:" + token);
            return null;
        }
        String strUser = jwt.getClaim("user").asString();
        if (MyStringUtil.isEmpty(strUser)) {
            log.error("token用户信息为空:" + token);
            throw new CustomException("非法token,user is null");
        }
        return strUser;
    }

    /**
     * 根据token获取code账号
     *
     * @param decodedJwt decodedJwt
     * @return code
     */
    public static String getManagerCode(DecodedJWT decodedJwt) {
        return decodedJwt.getClaim("userName").asString();
    }


    /**
     * 根据token获取用户信息
     *
     * @param token token
     * @return ManagerUser
     */
    public static String getManagerUser(String token) {
        if (MyStringUtil.isEmpty(token)) {
            return null;
        }
        DecodedJWT jwt = verifyManagerToken(token);
        if (jwt == null) {
            return null;
        }
        return builderManagerUser(jwt);
    }

    private static String builderManagerUser(DecodedJWT jwt) {
        return jwt.getClaim("userName").asString();
    }

    /**
     * 获取请求的token
     */
    private String getRequestToken() {
        String rToken = request.getHeader("rToken");
        if (StringUtil.isNotEmpty(rToken)) {
            return rToken;
        }
        // 从header中获取token
        String token = request.getHeader("token");
        // 如果header中不存在token,则从参数中获取token
        if (MyStringUtil.isEmpty(token)) {
            token = request.getParameter("token");
        }
        log.info("请求token:" + token);
        return token;
    }
}

五、Token使用

接下来就比较简单了,代码里面直接调用工具类将Token返回给前端;
代码如下:

 //获取Token  90|d Token的有效时间
        String token = tokenGenerator.generateManagerToken(username, "90|d");
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("token", token);

然后前端调用的时候请求头带上Token即可,下面的是PostMan请求示例:
在这里插入图片描述


总结

这就是Token校验的整个过程以及相关的代码了;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【Java】利用Token进行登录控制以及限制接口访问 的相关文章

随机推荐

  • 用Python预测收入,来看看你的收入到底应该是多少?

    Python界的网红机器学习 这股浪潮已经逐渐成为热点 而Python是机器学习方向的头牌语言 用机器学习来玩一些好玩的项目一定很有意思 比如根据你的职业 婚姻 家庭 教育时间等等来预测你的收入 这么神奇 不信的话 一起跟我往下看 1 数据
  • 如何使用chatGPT进行论文润色(中英文均可)

    1 为什么ChatGPT可以进行论文润色 ChatGPT本质是一个基于GPT3 5 应用在对话场景的超大语言模型 在各种数据集上经过训练而来的 很好的掌握了语言的 本质 特征 自然可以进行语言相关的工作 论文润色只是小事情 2 如何使用ch
  • 搭建简单的神经网络——使用pytorch实现鸢尾花的分类

    最近写毕业论文 看到网上的pytorch入门nn方法乱七八糟 遂写了本篇方法 好让更多的人可以使用pytorch实现简单的神经网络方法 version python 3 7 9 pytorch 1 7 0 function 利用神经网络进行
  • 区块链中的:哈希算法

    什么是哈希算法 哈希算法 又称散列算法 它是一个单向函数 可以把任意长度的输入数据转化为固定长度的输出 h H x h H x h H x 例如 对 morning 和 bitcoin 两个输入进行某种哈希运算 得到的结果是固定长度的数字
  • 当根据条件查询数据库中记录没有,但是又想返回0怎么办?

    我们平时在操作数据库的时候 对于null的记录或者字段相信大家都可以用ifnull 来判断为null的时候需求返回什么数据 但是如果根据条件查询的时候 数据库根本没有这条记录但是又想返回数据不存在时候的结果该怎么办 比如你统计一个时间区间的
  • 关于g2o的使用笔记

    文章目录 前言 一 g2o进行非线性优化 二 g2o进行前端位姿优化 三 g2o进行后端位姿优化 总结 前言 g2o是比较流行的图优化库 在视觉slam中的应用非常广泛 关于如何利用g2o求解BA优化问题 在此作个笔记 以供后面的学习中方便
  • webRTC的标准与发展

    Web实时通信 WebRTC 是标准 协议和JavaScript API的集合 两者的组合可实现浏览器 对等 之间的对等音频 视频和数据共享 WebRTC无需依赖第三方插件或专有软件 而是将实时通信转变为任何Web应用程序都可以通过简单的J
  • 【华为OD统一考试A卷

    华为OD统一考试A卷 B卷 新题库说明 2023年5月份 华为官方已经将的 2022 0223Q 1 2 3 4 统一修改为OD统一考试 A卷 和OD统一考试 B卷 你收到的链接上面会标注A卷还是B卷 请注意 根据反馈 目前大部分收到的都是
  • 一觉睡醒,ChatGPT 竟然被淘汰了?

    点击上方 码农突围 马上关注 这里是码农充电第一站 回复 666 获取一份专属大礼包 真爱 请设置 星标 或点个 在看 来源丨转自公众号 机器之心 编辑 杜伟 陈萍 OpenAI 的 Andrej Karpathy 都大力宣传 认为 Aut
  • Stream流(入门篇)

    目录 前言 1 Stream流概述 2 获取Stream流的方式 2 1 单列集合获取Stream流 2 2 双列集合获取Stream流 2 3 数组获取Stream流 2 4 零散数据获取Stream流 3 Stream流的中间方法 4
  • mybatisplus 增删改查&使用技巧

    一 查询条件使用 单个查询 如果返回多条会抛异常 User user userService getOne Wrappers
  • Docker-compose安装mysql

    介绍 本系列文章主要介绍使用docker compose部署mysql nginx redis等中间件 前后分离微服务项目部署流程 不介绍docker安装以及基础命令 话不多说首先进入mysql安装教学 操作 首先创建个目录用来存放dock
  • vue2和vue3的10种组件通信

    vue2和vue3的10种组件通信
  • Android 12(S) 版本适配指南

    前言 系统行为变更通常属于以下两种类别之一 面对所有应用的行为变更 运行在该系统版本上的所有应用都会影响 而无论应用的targetSDKVersion为何 通常应该先针对这些变更进行适配和测试 这有助于用户在新版本系统上运行你的应用时 用户
  • 打开多个Android Studio卡死的解决方法(提示内存不足)

    找到Android Studio的安装路径 打开bin文件夹下的studio exe vmoptions 可以用记事本打开 找到下面三个参数 默认设置的如下 Xms256m Java能够分配的内存 Xmx768m JAVA能够分配的最大内存
  • using namespace std 介绍

    using namespace std 首先我们要知道 这句代码的意思是 打开标准命名空间 即告诉编辑器我们将要使用名字空间std中的函数或者对象 using 意思就是正在使用的意思 namespace 的引用是为了解决不同space中命名
  • 浅析Java单例设计模式,自写demo,简单易懂

    单例模式特点 1 构造器私有 2 在一个Java应用程序中 可保证只有一个实例对象 3 只提供一个供外界调用的getInstance 方法 单例模式优点 1 减少某些对象的频繁创建 降低系统开销和内存占用 2 外部调用不使用new关键字 降
  • 每次运行项目都会出现这个reload script assemblies

    会卡死的话试一下 Window gt Package Manager 然后去更新跟删掉你不用的 想直接就让它不出现的话 设置成这个样子 但是这样设置是有问题的具体看官方文档 域重新加载 Unity 手册
  • 语义分割网络经典:unet

    点击上方 小白学视觉 选择加 星标 或 置顶 重磅干货 第一时间送达 作者 晟 沚 编辑 赵一帆 目前分割主要存在问题 分割网络中的池化操作在减少feature的空间分辨率的同时增加了模型感受野 这也是模型应对小型平移具有鲁棒性的根本原因
  • 【Java】利用Token进行登录控制以及限制接口访问

    文章目录 前言 一 pom xml 二 ShiroConfig 三 oauth2 3 1 OAuth2Filter 3 2 OAuth2Realm 3 3 OAuth2Token 四 Token工具类 4 1 TokenAesUtil 4