精华内容
下载资源
问答
  • 主要为大家详细介绍了SpringBoot框架集成token实现登录校验功能,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
  • 一、场景与环境 最近需要写一下前后端分离下的登录解决方案,目前大多数都采用请求头携带 Token 的...  c、前端在此后的每次请求,都会携带token与后端校验;   d、在token有效时间内前端的请求响应都会成功,
  • 主要介绍了SpringBoot集成JWT生成token校验方法过程解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 现在越来越多的登录方式都用到了token作为用户登录令牌,所以实现了一个token生成和校验案例。缺点:该实现方式token是存储在内存中,不适合分布式项目,如需改为分布式项目部署,可把token存储在redis中,其中的...

    现在越来越多的登录方式都用到了token作为用户登录令牌,所以实现了一个token生成和校验案例。

    缺点:该实现方式token是存储在内存中,不适合分布式项目,如需改为分布式项目部署,可把token存储在redis中,其中的实现原理还是保持不变。

    一)token编码工具类

    package com.oysept.token.utils;

    /**

    * token编码工具类

    * @author ouyangjun

    */

    public class TokenEncryptUtils {

    // 编码密码,可自定义

    private static final String ENCODED_PASSWORD = "ouyangjun";

    /**

    * 编码

    * @param str

    * @return

    */

    public static String encoded(String str) {

    return strToHex(encodedString(str, ENCODED_PASSWORD));

    }

    /**

    * 转换

    * @param str

    * @param password

    * @return

    */

    private static String encodedString(String str, String password) {

    char[] pwd = password.toCharArray();

    int pwdLen = pwd.length;

    char[] strArray = str.toCharArray();

    for (int i=0; i

    strArray[i] = (char)(strArray[i] ^ pwd[i%pwdLen] ^ pwdLen);

    }

    return new String(strArray);

    }

    private static String strToHex(String s) {

    return bytesToHexStr(s.getBytes());

    }

    private static String bytesToHexStr(byte[] bytesArray) {

    StringBuilder builder = new StringBuilder();

    String hexStr;

    for (byte bt : bytesArray) {

    hexStr = Integer.toHexString(bt & 0xFF);

    if (hexStr.length() == 1) {

    builder.append("0");

    builder.append(hexStr);

    }else{

    builder.append(hexStr);

    }

    }

    return builder.toString();

    }

    /**

    * 解码

    * @param str

    * @return

    */

    public static String decoded(String str) {

    String hexStr = null;

    try {

    hexStr = hexStrToStr(str);

    } catch (Exception e) {

    e.printStackTrace();

    }

    if (hexStr != null) {

    hexStr = encodedString(hexStr, ENCODED_PASSWORD);

    }

    return hexStr;

    }

    private static String hexStrToStr(String hexStr) {

    return new String(hexStrToBytes(hexStr));

    }

    private static byte[] hexStrToBytes(String hexStr) {

    String hex;

    int val;

    byte[] btHexStr = new byte[hexStr.length()/2];

    for (int i=0; i

    hex = hexStr.substring(2*i, 2*i+2);

    val = Integer.valueOf(hex, 16);

    btHexStr[i] = (byte) val;

    }

    return btHexStr;

    }

    }

    二)token生成和校验工具类(包含main方法测试)

    package com.oysept.token.utils;

    import java.util.HashMap;

    import java.util.Map;

    import java.util.Map.Entry;

    /**

    * token生成和校验

    * @author ouyangjun

    */

    public class TokenUtils {

    private static Map MAP_TOKENS = new HashMap();

    private static final int VALID_TIME = 60*60*2; // token有效期(秒)

    public static final String TOKEN_ERROR = "F"; // 非法

    public static final String TOKEN_OVERDUE = "G"; // 过期

    public static final String TOKEN_FAILURE = "S"; // 失效

    /**

    * 生成token,该token长度不一致,如需一致,可自行MD5或者其它方式加密一下

    * 该方式的token只存在磁盘上,如果项目是分布式,最好用redis存储

    * @param str: 该字符串可自定义,在校验token时要保持一致

    * @return

    */

    public static String getToken(String str) {

    String token = TokenEncryptUtils.encoded(getCurrentTime()+","+str);

    MAP_TOKENS.put(str, token);

    return token;

    }

    /**

    * 校验token的有效性

    * @param token

    * @return

    */

    public static String checkToken(String token) {

    if (token == null) {

    return TOKEN_ERROR;

    }

    try{

    String[] tArr = TokenEncryptUtils.decoded(token).split(",");

    if (tArr.length != 2) {

    return TOKEN_ERROR;

    }

    // token生成时间戳

    int tokenTime = Integer.parseInt(tArr[0]);

    // 当前时间戳

    int currentTime = getCurrentTime();

    if (currentTime-tokenTime < VALID_TIME) {

    String tokenStr = tArr[1];

    String mToken = MAP_TOKENS.get(tokenStr);

    if (mToken == null) {

    return TOKEN_OVERDUE;

    } else if(!mToken.equals(token)) {

    return TOKEN_FAILURE;

    }

    return tokenStr;

    } else {

    return TOKEN_OVERDUE;

    }

    }catch (Exception e) {

    e.printStackTrace();

    }

    return TOKEN_ERROR;

    }

    /**获取当前时间戳(10位整数)*/

    public static int getCurrentTime() {

    return (int)(System.currentTimeMillis()/1000);

    }

    /**

    * 移除过期的token

    */

    public static void removeInvalidToken() {

    int currentTime = getCurrentTime();

    for (Entry entry : MAP_TOKENS.entrySet()) {

    String[] tArr = TokenEncryptUtils.decoded(entry.getValue()).split(",");

    int tokenTime = Integer.parseInt(tArr[0]);

    if(currentTime-tokenTime > VALID_TIME){

    MAP_TOKENS.remove(entry.getKey());

    }

    }

    }

    /**

    * 测试

    * @param args

    */

    public static void main(String[] args) {

    String str = "username_and_password";

    // 获取token

    String token = TokenUtils.getToken(str);

    System.out.println("token Result: " + token);

    // 校验token

    String checkToken = TokenUtils.checkToken(token);

    System.out.println("checkToken Result: " + checkToken);

    if(str.equals(checkToken)) {

    System.out.println("==>token verification succeeded!");

    }

    }

    }

    补充知识:JAVA后端生成Token(令牌),用于校验客户端,防止重复提交

    1.概述:在web项目中,服务端和前端经常需要交互数据,有的时候由于网络相应慢,客户端在提交某些敏感数据(比如按照正常的业务逻辑,此份数据只能保存一份)时,如果前端多次点击提交按钮会导致提交多份数据,这种情况我们是要防止发生的。

    2.解决方法:

    ①前端处理:在提交之后通过js立即将按钮隐藏或者置为不可用。

    ②后端处理:对于每次提交到后台的数据必须校验,也就是通过前端携带的令牌(一串唯一字符串)与后端校验来判断当前数据是否有效。

    3.总结:第一种方法相对来说比较简单,但是安全系数不高,第二种方法从根本上解决了问题,所以我推荐第二种方法。

    4.核心代码:

    生成Token的工具类:

    /**

    * 生成Token的工具类:

    */

    package red.hearing.eval.modules.token;

    import java.security.MessageDigest;

    import java.security.NoSuchAlgorithmException;

    import java.util.Random;

    import sun.misc.BASE64Encoder;

    /**

    * 生成Token的工具类

    * @author zhous

    * @since 2018-2-23 13:59:27

    *

    */

    public class TokenProccessor {

    private TokenProccessor(){};

    private static final TokenProccessor instance = new TokenProccessor();

    public static TokenProccessor getInstance() {

    return instance;

    }

    /**

    * 生成Token

    * @return

    */

    public String makeToken() {

    String token = (System.currentTimeMillis() + new Random().nextInt(999999999)) + "";

    try {

    MessageDigest md = MessageDigest.getInstance("md5");

    byte md5[] = md.digest(token.getBytes());

    BASE64Encoder encoder = new BASE64Encoder();

    return encoder.encode(md5);

    } catch (NoSuchAlgorithmException e) {

    // TODO Auto-generated catch block

    e.printStackTrace();

    }

    return null;

    }

    }

    Token通用工具类:

    /**

    *

    */

    package red.hearing.eval.modules.token;

    import javax.servlet.http.HttpServletRequest;

    import org.apache.commons.lang3.StringUtils;

    /**

    * Token的工具类

    * @author zhous

    * @since 2018-2-23 14:01:41

    *

    */

    public class TokenTools {

    /**

    * 生成token放入session

    * @param request

    * @param tokenServerkey

    */

    public static void createToken(HttpServletRequest request,String tokenServerkey){

    String token = TokenProccessor.getInstance().makeToken();

    request.getSession().setAttribute(tokenServerkey, token);

    }

    /**

    * 移除token

    * @param request

    * @param tokenServerkey

    */

    public static void removeToken(HttpServletRequest request,String tokenServerkey){

    request.getSession().removeAttribute(tokenServerkey);

    }

    /**

    * 判断请求参数中的token是否和session中一致

    * @param request

    * @param tokenClientkey

    * @param tokenServerkey

    * @return

    */

    public static boolean judgeTokenIsEqual(HttpServletRequest request,String tokenClientkey,String tokenServerkey){

    String token_client = request.getParameter(tokenClientkey);

    if(StringUtils.isEmpty(token_client)){

    return false;

    }

    String token_server = (String) request.getSession().getAttribute(tokenServerkey);

    if(StringUtils.isEmpty(token_server)){

    return false;

    }

    if(!token_server.equals(token_client)){

    return false;

    }

    return true;

    }

    }

    使用方法:

    ①在输出前端页面的时候调用TokenTools.createToken方法,会把本次生成的token放入session中。

    ②然后在前端页面提交数据时从session中获取token,然后添加到要提交的数据中。

    ③服务端接受数据后调用judgeTokenIsEqual方法判断两个token是否一致,如果不一致则返回,不进行处理。

    备注:tokenClientkey和tokenServerkey自定义,调用judgeTokenIsEqual方法时的tokenClientkey一定要与前端页面的key一致。

    以上这篇java token生成和校验的实例代码就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。

    展开全文
  • SpringBoot框架集成token实现登录校验功能(APP)

    万次阅读 多人点赞 2019-04-18 14:00:56
    公司新项目,需要做移动端(Android和IOS),登录模块,两个移动端人员提出用token校验登录状态,一脸懵懵的,没做过,对于token的基本定义都模棱两可,然后查资料查查查,最终OK完成,写篇博客记录一下 ...

    简介

    公司新项目,需要做移动端(Android和IOS),登录模块,两个移动端人员提出用token来校验登录状态,一脸懵懵的,没做过,对于token的基本定义都模棱两可,然后查资料查查查,最终OK完成,写篇博客记录一下

    思路:

    1、基于session登录

    基于session的登录(有回话状态),用户携带账号密码发送请求向服务器,服务器进行判断,成功后将用户信息放入session,用户发送请求判断session中是否有用户信息,有的话放行,没有的话进行拦截,但是考虑到时App产品,牵扯到要判断用户的session,需要sessionID,还要根据sessionId来获取session,在进行校验,还有sessionId的一个存储等等,所以没考虑用session

    2、基于token登录

    基于token的登录,是不存在回话状态,大概思路,在用户初次等路的时候,校验用户账号密码,成功后给其生成一个token,token=用户ID+时间戳+过期时间+一个自己平台规定的签名,使用jjwt生成一个令牌,然后对其进行存库,用户每次访问接口,都会在头部Headers中带上token,后来拦截器对其进行拦截,如果token为空或错误则让其登录,如果有token,获取token进行其解析,取出里面的用户ID,根据用户ID查询数据库中所存token,判断其是否正确,正确使其登录,错误则提示登录,大致思路就是这样,下面开始代码

    导入jar包

    <!-- 生成token -->
    <dependency>
        <groupId>io.jsonwebtoken</groupId>
        <artifactId>jjwt</artifactId>
        <version>0.9.0</version>
    </dependency>

    开发步骤

    1、创建token库

    2、创建token实体类

    package com.prereadweb.user.entity;
    
    import lombok.Data;
    
    /**
     * @Description: Token实体类
     * @author: Yangxf
     * @date: 2019/4/14 12:53
     */
    @Data
    public class TokenEntity {
    
        /* tokenId */
        private Long id;
    
        /* 用户ID */
        private Long userId;
    
        /* 刷新时间 */
        private int buildTime;
    
        /* token */
        private String token;
    
    }

    3、编写token的三个方法(添加、查询、修改)

    package com.prereadweb.user.mapper;
    
    import com.prereadweb.user.entity.TokenEntity;
    import org.apache.ibatis.annotations.Mapper;
    
    /**
     * @Description: Token数据库持久层接口
     * @author: Yangxf
     * @date: 2019/4/14 13:00
     */
    @Mapper
    public interface TokenMapper {
    
        /* 添加token */
        void addToken(TokenEntity token);
    
        /* 修改token */
        void updataToken(TokenEntity token);
    
        /* 查询token */
        TokenEntity findByUserId(Long userId);
    
    }

    4、创建拦截器

    package com.prereadweb.user.interceptor;
    
    import com.prereadweb.user.entity.TokenEntity;
    import com.prereadweb.user.mapper.TokenMapper;
    import io.jsonwebtoken.Claims;
    import io.jsonwebtoken.Jwts;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.web.servlet.HandlerInterceptor;
    import org.springframework.web.servlet.ModelAndView;
    
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
    import java.util.Date;
    
    /**
     * @Description:拦截器
     * @author: Yangxf
     * @date: 2019/4/14 12:58
     */
    public class LoginInterceptor implements HandlerInterceptor {
    
        @Autowired
        protected TokenMapper tokenMapper;
        //提供查询
        @Override
        public void afterCompletion(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, Exception arg3)
                throws Exception {}
        @Override
        public void postHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2, ModelAndView arg3)
                throws Exception {}
        @Override
        public boolean preHandle(HttpServletRequest arg0, HttpServletResponse arg1, Object arg2) throws Exception {
            //此处为不需要登录的接口放行
            if (arg0.getRequestURI().contains("/login") || arg0.getRequestURI().contains("/register") || arg0.getRequestURI().contains("/error") || arg0.getRequestURI().contains("/static")) {
                return true;
            }
            //权限路径拦截
            //PrintWriter resultWriter = arg1.getOutputStream();
            // TODO: 有时候用PrintWriter 回报 getWriter() has already been called for this response
            //换成ServletOutputStream就OK了
            arg1.setContentType("text/html;charset=utf-8");
            ServletOutputStream resultWriter = arg1.getOutputStream();
            final String headerToken=arg0.getHeader("token");
            //判断请求信息
            if(null==headerToken||headerToken.trim().equals("")){
                resultWriter.write("你没有token,需要登录".getBytes());
                resultWriter.flush();
                resultWriter.close();
                return false;
            }
            //解析Token信息
            try {
                Claims claims = Jwts.parser().setSigningKey("preRead").parseClaimsJws(headerToken).getBody();
                String tokenUserId=(String)claims.get("userId");
                long iTokenUserId = Long.parseLong(tokenUserId);
                //根据客户Token查找数据库Token
                TokenEntity myToken= tokenMapper.findByUserId(iTokenUserId);
    
                //数据库没有Token记录
                if(null==myToken) {
                    resultWriter.write("我没有你的token?,需要登录".getBytes());
                    resultWriter.flush();
                    resultWriter.close();
                    return false;
                }
                //数据库Token与客户Token比较
                if( !headerToken.equals(myToken.getToken()) ){
                    resultWriter.print("你的token修改过?,需要登录");
                    resultWriter.flush();
                    resultWriter.close();
                    return false;
                }
                //判断Token过期
                Date tokenDate= claims.getExpiration();
                int overTime=(int)(new Date().getTime()-tokenDate.getTime())/1000;
                if(overTime>60*60*24*3){
                    resultWriter.write("你的token过期了?,需要登录".getBytes());
                    resultWriter.flush();
                    resultWriter.close();
                    return false;
                }
    
            } catch (Exception e) {
                resultWriter.write("反正token不对,需要登录".getBytes());
                resultWriter.flush();
                resultWriter.close();
                return false;
            }
            //最后才放行
            return true;
        }
    
    }

    5、配置拦截器

    package com.prereadweb.user.config;
    
    import com.prereadweb.user.interceptor.LoginInterceptor;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
    import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
    
    /**
     * @Description: 拦截器配置
     * @author: Yangxf
     * @date: 2019/4/14 13:09
     */
    @Configuration
    public class LoginConfiguration implements WebMvcConfigurer {
        
        /**
         * @Function: 这个方法才能在拦截器中自动注入查询数据库的对象
         * @author:   YangXueFeng
         * @Date:     2019/4/14 13:10
         */
        @Bean
        LoginInterceptor loginInterceptor() {
            return new LoginInterceptor();
        }
        
        /**
         * @Function: 配置生成器:添加一个拦截器,拦截路径为login以后的路径
         * @author:   YangXueFeng
         * @Date:     2019/4/14 13:10
         */
        @Override
        public void addInterceptors(InterceptorRegistry registry ){
            registry.addInterceptor(loginInterceptor()).addPathPatterns("/**").excludePathPatterns("/login", "/register", "/static");
        }
    
    }

    6、登录

    controller层

     @RequestMapping("/getlogin")
        public Object login(@Param("..") LoginQueryForm loginForm) {
            return userViewService.login(loginForm);
        }

    serrvice层

    @Override
        public Map<String, Object> login(LoginQueryForm loginForm) {
    
            Map<String, Object> map = new HashMap<>();
            //手机验证码登录
            if(!Util.isEmpty(loginForm.getPhoneCode())) {
                return phoneCodeLogin(loginForm, map);
            }
            //判断用户信息为空
            if (Util.isEmpty(loginForm.getPhone()) || Util.isEmpty(loginForm.getLoginPwd())) {
                return checkParameter(map);
            }
            //根据手机号查询user对象
            UserEntity user = userMapper.getUser(loginForm.getPhone());
    
            //判断用户不存在
            if (Util.isEmpty(user)) {
                map.put("code", UserStatusEnum.USER_NON_EXISTENT.intKey());
                map.put("msg", UserStatusEnum.USER_NON_EXISTENT.value());
                return map;
            }
            /* 判断密码 */
            if(!MD5Util.string2MD5(loginForm.getLoginPwd()).equals(user.getLoginPwd())){
                map.put("code", UserStatusEnum.PWD_ERROR.intKey());
                map.put("msg", UserStatusEnum.PWD_ERROR.value());
                return map;
            }
    
            //根据数据库的用户信息查询Token
            return operateToKen(map, user, user.getId());
        }

    token操作

    private Map<String, Object> operateToKen(Map<String, Object> map, UserEntity user, long userId) {
            //根据数据库的用户信息查询Token
            TokenEntity token = tokenmapper.findByUserId(userId);
            //为生成Token准备
            String TokenStr = "";
            Date date = new Date();
            int nowTime = (int) (date.getTime() / 1000);
            //生成Token
            TokenStr = creatToken(userId, date);
            if (null == token) {
                //第一次登陆
                token = new TokenEntity();
                token.setToken(TokenStr);
                token.setBuildTime(nowTime);
                token.setUserId(userId);
                token.setId(Long.valueOf(IdUtils.getPrimaryKey()));
                tokenmapper.addToken(token);
            }else{
                //登陆就更新Token信息
                TokenStr = creatToken(userId, date);
                token.setToken(TokenStr);
                token.setBuildTime(nowTime);
                tokenmapper.updataToken(token);
            }
            UserQueryForm queryForm = getUserInfo(user, TokenStr);
            /* 将用户信息存入session */
            /*SessionContext sessionContext = SessionContext.getInstance();
            HttpSession session = sessionContext.getSession();
            httpSession.setAttribute("userInfo", user);*/
            //返回Token信息给客户端
            successful(map);
            map.put("data", queryForm);
            return map;
        }

    生成token

    private String creatToken(Long userId, Date date) {
            SignatureAlgorithm signatureAlgorithm = SignatureAlgorithm.HS256;
            JwtBuilder builder = Jwts.builder().setHeaderParam("typ", "JWT") // 设置header
                    .setHeaderParam("alg", "HS256").setIssuedAt(date) // 设置签发时间
                    .setExpiration(new Date(date.getTime() + 1000 * 60 * 60))
                    .claim("userId",String.valueOf(userId) ) // 设置内容
                    .setIssuer("lws")// 设置签发人
                    .signWith(signatureAlgorithm, "签名"); // 签名,需要算法和key
            String jwt = builder.compact();
            return jwt;
        }

    至此,token登录OK

    展开全文
  • 后端通过注解进行token校验

    千次阅读 2020-05-11 10:26:28
    1.自定义注解 @Target(ElementType.METHOD) ...2.拦截器获取并校验token 注:自定义token处理逻辑 @Component @Slf4j public class AuthorizationInterceptor extends HandlerInterceptorAdapter { @Autowired p

    1.自定义注解

    @Target(ElementType.METHOD)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    public @interface Login {
    }
    

    2.拦截器获取并校验token
    注:自定义token处理逻辑

    @Component
    @Slf4j
    public class AuthorizationInterceptor extends HandlerInterceptorAdapter {
        @Autowired
        private JwtUtils jwtUtils;
    
        public static final String USER_KEY = "userId";
    
        @Override
        public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
            Login annotation;
            if(handler instanceof HandlerMethod) {
                annotation = ((HandlerMethod) handler).getMethodAnnotation(Login.class);
            }else{
                return true;
            }
    
            if(annotation == null){
                return true;
            }
    
            //获取用户凭证
            String token = request.getHeader(jwtUtils.getHeader());
            if(StringUtils.isBlank(token)){
                token = request.getParameter(jwtUtils.getHeader());
            }
    
            //凭证为空
            if(StringUtils.isBlank(token)){
                throw new RRException(jwtUtils.getHeader() + "不能为空", HttpStatus.UNAUTHORIZED.value());
            }
    
            Claims claims = jwtUtils.getClaimByToken(token);
            if(claims == null || jwtUtils.isTokenExpired(claims.getExpiration())){
                throw new RRException(jwtUtils.getHeader() + "失效,请重新登录", HttpStatus.UNAUTHORIZED.value());
            }
    
            //设置userId到request里,后续根据userId,获取用户信息
            request.setAttribute(USER_KEY, Long.parseLong(claims.getSubject()));
            log.info("入参:{}",request.getParameterMap());
            return true;
        }
    }
    

    3.JWTtoken生成、校验

    @ConfigurationProperties(prefix = "token.jwt")
    @Component
    public class JwtUtils {
        private Logger logger = LoggerFactory.getLogger(getClass());
    
        private String secret;
        private long expire;
        private String header;
    
        /**
         * 生成jwt token
         */
        public String generateToken(long userId) {
            Date nowDate = new Date();
            //过期时间
            Date expireDate = new Date(nowDate.getTime() + expire * 1000);
    
            return Jwts.builder()
                    .setHeaderParam("typ", "JWT")
                    .setSubject(userId+"")
                    .setIssuedAt(nowDate)
                    .setExpiration(expireDate)
                    .signWith(SignatureAlgorithm.HS512, secret)
                    .compact();
        }
    
        public Claims getClaimByToken(String token) {
            try {
                return Jwts.parser()
                        .setSigningKey(secret)
                        .parseClaimsJws(token)
                        .getBody();
            }catch (Exception e){
                logger.debug("validate is token error ", e);
                return null;
            }
        }
    
        /**
         * token是否过期
         * @return  true:过期
         */
        public boolean isTokenExpired(Date expiration) {
            return expiration.before(new Date());
        }
    
        public String getSecret() {
            return secret;
        }
    
        public void setSecret(String secret) {
            this.secret = secret;
        }
    
        public long getExpire() {
            return expire;
        }
    
        public void setExpire(long expire) {
            this.expire = expire;
        }
    
        public String getHeader() {
            return header;
        }
    
        public void setHeader(String header) {
            this.header = header;
        }
    }
    
    

    4.配置token有效期

    token:
      jwt:
        # 加密秘钥
        secret: f4e2e52034348f86b67cde581c0f9eb5[www.renren.io]
        # token有效时长,7天,单位秒
        expire: 604800
        header: token
    

    5.Controller方法使用注解验证token

    @RestController
    @RequestMapping("/app")
    @Api("APP测试接口")
    public class AppTestController {
    	@Autowired
    	private SysConfigService sysConfigService;
    
    	@Login
    	@GetMapping("userId")
    	@ApiOperation("获取用户ID")
    	public R userInfo(@RequestAttribute("userId") Integer userId) {
    		return R.ok().put("userId", userId);
    	}
    
    	@GetMapping("notToken")
    	@ApiOperation("忽略Token验证测试")
    	public R notToken() {
    		return R.ok().put("msg", "无需token也能访问。。。");
    	}
    }
    
    
    展开全文
  • java token生成和校验的一个案例

    万次阅读 2019-01-28 14:48:38
    现在越来越多的登录方式都用到了token作为用户登录令牌,所以实现了一个token生成和校验案例。 缺点:该实现方式token是存储在内存中,不适合分布式项目,如需改为分布式项目部署,可把token存储在redis中,其中的...

    现在越来越多的登录方式都用到了token作为用户登录令牌,所以实现了一个token生成和校验案例。

    缺点:该实现方式token是存储在内存中,不适合分布式项目,如需改为分布式项目部署,可把token存储在redis中,其中的实现原理还是保持不变。

    一)token编码工具类

    package com.oysept.token.utils;
    
    /**
     * token编码工具类
     * @author ouyangjun
     */
    public class TokenEncryptUtils {
    	
    	// 编码密码,可自定义
    	private static final String ENCODED_PASSWORD = "ouyangjun";
    	
    	/**
    	 * 编码
    	 * @param str
    	 * @return
    	 */
    	public static String encoded(String str) {
    		return strToHex(encodedString(str, ENCODED_PASSWORD));
    	}
    	
    	/**
    	 * 转换
    	 * @param str
    	 * @param password
    	 * @return
    	 */
    	private static String encodedString(String str, String password) {
    		char[] pwd = password.toCharArray();
    		int pwdLen = pwd.length;
    		
            char[] strArray = str.toCharArray();
            for (int i=0; i<strArray.length; i++) {
            	strArray[i] = (char)(strArray[i] ^ pwd[i%pwdLen] ^ pwdLen);
            }
            return new String(strArray);
    	}
    	
    	private static String strToHex(String s) {
    		return bytesToHexStr(s.getBytes());
    	}
    	
    	private static String bytesToHexStr(byte[] bytesArray) {
    		StringBuilder builder = new StringBuilder();
    		String hexStr;
    		for (byte bt : bytesArray) {
    			hexStr = Integer.toHexString(bt & 0xFF);
    			if (hexStr.length() == 1) {
    				builder.append("0");
    				builder.append(hexStr);
    			}else{
    				builder.append(hexStr);
    			}
    		}
    		return builder.toString();
    	}
    	
    	/**
    	 * 解码
    	 * @param str
    	 * @return
    	 */
    	public static String decoded(String str) {
    		String hexStr = null;
    		try {
    			hexStr = hexStrToStr(str);
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		if (hexStr != null) {
    			hexStr = encodedString(hexStr, ENCODED_PASSWORD);
    		}
    		return hexStr;
    	}
    	
    	private static String hexStrToStr(String hexStr) {
    		return new String(hexStrToBytes(hexStr));
    	}
    	
    	private static byte[] hexStrToBytes(String hexStr) {
    		String hex;
    		int val;
    		byte[] btHexStr = new byte[hexStr.length()/2];
    		for (int i=0; i<btHexStr.length; i++) {
    			hex = hexStr.substring(2*i, 2*i+2);
    			val = Integer.valueOf(hex, 16);
    			btHexStr[i] = (byte) val;
    		}
    		return btHexStr;
    	}
    	
    }
    

    二)token生成和校验工具类(包含main方法测试)

    package com.oysept.token.utils;
    
    import java.util.HashMap;
    import java.util.Map;
    import java.util.Map.Entry;
    
    /**
     * token生成和校验
     * @author ouyangjun
     */
    public class TokenUtils {
    
    	private static Map<String,String> MAP_TOKENS = new HashMap<String,String>();
    	private static final int VALID_TIME = 60*60*2; // token有效期(秒)
    	public static final String TOKEN_ERROR = "F"; // 非法
    	public static final String TOKEN_OVERDUE = "G"; // 过期
    	public static final String TOKEN_FAILURE = "S"; // 失效
    	
    	/**
    	 * 生成token,该token长度不一致,如需一致,可自行MD5或者其它方式加密一下
    	 * 该方式的token只存在磁盘上,如果项目是分布式,最好用redis存储
    	 * @param str: 该字符串可自定义,在校验token时要保持一致
    	 * @return
    	 */
    	public static String getToken(String str) {
    		String token = TokenEncryptUtils.encoded(getCurrentTime()+","+str);
    		MAP_TOKENS.put(str, token);
    		return token;
    	}
    	
    	/**
    	 * 校验token的有效性
    	 * @param token
    	 * @return
    	 */
    	public static String checkToken(String token) {
    		if (token == null) {
    			return TOKEN_ERROR;
    		}
    		try{
    			String[] tArr = TokenEncryptUtils.decoded(token).split(",");
    			if (tArr.length != 2) {
    				return TOKEN_ERROR;
    			}
    			// token生成时间戳
    			int tokenTime = Integer.parseInt(tArr[0]);
    			// 当前时间戳
    			int currentTime = getCurrentTime();
    			if (currentTime-tokenTime < VALID_TIME) {
    				String tokenStr = tArr[1];
    				String mToken = MAP_TOKENS.get(tokenStr);
    				if (mToken == null) {
    					return TOKEN_OVERDUE;
    				} else if(!mToken.equals(token)) {
    					return TOKEN_FAILURE;
    				}
    				return tokenStr;
    			} else {
    				return TOKEN_OVERDUE;
    			}
    		}catch (Exception e) {
    			e.printStackTrace();
    		}
    		return TOKEN_ERROR;
    	}
    	
    	/**获取当前时间戳(10位整数)*/
    	public static int getCurrentTime() {
    		return (int)(System.currentTimeMillis()/1000);
    	}
    	
    	/**
    	 * 移除过期的token
    	 */
    	public static void removeInvalidToken() {
    		int currentTime = getCurrentTime();
    		for (Entry<String,String> entry : MAP_TOKENS.entrySet()) {
    			String[] tArr = TokenEncryptUtils.decoded(entry.getValue()).split(",");
    			int tokenTime = Integer.parseInt(tArr[0]);
    			if(currentTime-tokenTime > VALID_TIME){
    				MAP_TOKENS.remove(entry.getKey());
    			}
    		}
    	}
    	
    	/**
    	 * 测试
    	 * @param args
    	 */
    	public static void main(String[] args) {
    		String str = "username_and_password";
    		
    		// 获取token
    		String token = TokenUtils.getToken(str);
    		System.out.println("token Result: " + token);
    		
    		// 校验token
    		String checkToken = TokenUtils.checkToken(token);
    		System.out.println("checkToken Result: " + checkToken);
    		if(str.equals(checkToken)) {
    			System.out.println("==>token verification succeeded!");
    		}
    		
    	}
    	
    }
    

    本章完结,待续!

     

    本文说明:该文章属于原创,如需转载,请标明文章转载来源

    展开全文
  • token校验机制

    千次阅读 2021-11-15 17:34:19
    token校验机制 什么是token token是客户端登陆的时候由服务端生成,之后每次请求都需要携带token进行请求。校验用户身份呢的作用 为什么使用token 减少敏感信息的传递 可以校验用户身份的准确性以及有效期 单...
  • 拦截器实现token校验

    2021-06-21 11:18:06
    token校验 1、实现HandlerInterceptorAdapter接口 /** * token校验拦截器 * * @author LIUQI */ @Component public class RepeatSubmitInterceptor extends HandlerInterceptorAdapter { @Resource RedisUtil...
  • 用户编号都是通过接口明文传输,稍微懂点技术的都可以利用请求监控拿到请求的URL和参数,由于之前都是赶业务需求,导致后端整体安全性偏低了,所以趁着这次redis也在应用中,所以决定在zuul中加入一个token授权功能...
  • JWT生成Token做登录校验讲解

    千次阅读 2018-08-01 16:01:59
    JWT(json web token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。 JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。比如用在用户登录上...
  • JWT生成Token做登录校验

    万次阅读 2018-06-02 11:31:08
    JWT简介JWT(json web token)是为了在网络应用环境间传递声明而执行的一种基于JSON的开放标准。JWT的声明一般被用来在身份提供者和服务提供者间传递被认证的用户身份信息,以便于从资源服务器获取资源。比如用在用户...
  • 申请微信测试账号测试支付功能,需要填写URL和Token校验服务器,整了一天,终于整出来了,微信就是没有支付宝方便,不想喷微信了,麻烦,复杂, 但是还是整出来来了 新建项目,把代码copy进去,部署到服务器上,代码...
  • 使用springBoot实现token校验 添加authorToken的依赖包 <dependency> <groupId>com.auth0</groupId> <artifactId>java-jwt</artifactId> <version>3.8.2</version>...
  • filter 过滤器 token 校验

    千次阅读 2019-04-25 09:43:25
    //如果请求的url 中包含 /web/,则进行token校验 if (request.getRequestURI().indexOf("/web/") != -1) { Map,Object> result = new HashMap,Object>(); String accessToken = request.getHeader("webToken"); ...
  • 来源:blog.csdn.net/qq_33556185/article/details/1054202051.定义Token的注解,需要Token校验的接口,方法上加上此注解import...
  • Jwt生成token以及token过期校验

    万次阅读 2019-12-06 09:48:02
    1 什么是JJWT ​ JJWT是一个提供端到端的JWT创建和验证的Java库。永远免费和开源(Apache License,版本2.0),JJWT很容易使用和理解。它被设计成一个以建筑为中心的流畅界面,隐藏了它的大部分复杂性。 2 JJWT快速...
  • 配置拦截器校验token

    2020-09-30 10:55:58
    Object handler) { // 下面两个判断是基于注解,判断接口上是否配置了自定义注解,只有添加了自定义注解才校验token // 因为拦截器只想在需要token信息的接口做校验,所以做了这个判断,如果所有token都想校验...
  • 自定义注解校验Token

    千次阅读 2018-08-24 11:35:26
    小伙伴在系统开发过程中,会遇到部分接口需要授权才能请求的问题,通常的做法是服务端...利用过滤器实现,放掉不需要校验的接口,然后校验剩余接口的token. 此方法配置略显复杂,静态资源什么的也需要配置,比较麻...
  • 本文记录了Django如何应用jwt进行身份校验token
  • Spring Cloud Gateway 实现Token校验

    千次阅读 2020-07-16 17:53:14
    SpringCloud视频教程: ...from_uin=171851697&...http://www.51ufo.cn/%E5%BE%AE%E6%9C%8D%E5%8A%A1/%E5%88%86%E5%B8%83%E5%BC%8F/2020/07/16/Spring-Cloud-Gateway-%E5%AE%9E%E7%8E%B0Token%E6%A0%A
  • 权限校验或者身份验证就不得不提 Token,目前 Token 的验证方式有很多种,有生成 Token 后将 Token 存储在 Redis 或数据库的,也有很多用 JWT(JSON Web Token)的。 说实话这方面我的经验不多,又着急赶项目,所以...
  • SpringBoot开发Keycloak token的获取以及校验通过Keycloak的登录页跳转Client方式获取tokenclient开发查看token获取token通过接口校验token校验tokenKeycloak依赖包如下 通过Keycloak的登录页跳转Client方式获取...
  • Retrofit2图片上传下载带token校验,博客地址:https://blog.csdn.net/dreams_deng/article/details/104823070
  • java下的token校验

    千次阅读 2016-05-08 19:57:09
    参数 描述 signature 微信加密签名,signature结合了开发者填写的token参数和请求中的timestamp参数、nonce参数。 timestamp 时间戳 nonce 随机数
  • 主要介绍了JAVA中的Token 基于Token的身份验证实例,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
  • 资源服务器在获取到了客户端发送过来的token后,做的第一件事情就是校验该token的真伪性,如果token校验不通过,则不允许调用对应的接口。 当前Spring Cloud与OAth2.0整合的版本依赖为: <dependency> <...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 71,199
精华内容 28,479
关键字:

token主要是校验什么