首页 > 其他分享 >如何使用token进行身份认证

如何使用token进行身份认证

时间:2023-07-03 17:22:42浏览次数:36  
标签:String 用户 认证 token ID public 身份

如何使用token进行身份认证

什么是token?

token是一种用于身份认证的技术,它是一个包含用户信息和签名的字符串,通常由服务器生成并返回给客户端。客户端在每次请求时,都需要携带token来证明自己的身份。服务器通过验证token的有效性和完整性,来授权客户端访问受保护的资源。

为什么要使用token?

使用token进行身份认证有以下几个优点:

  • 无状态:token不需要服务器存储或维护,可以减轻服务器的负担,提高性能和可扩展性。
  • 安全:token可以防止重放攻击,因为每个token都有一个过期时间,过期后就无法使用。token也可以防止篡改攻击,因为每个token都有一个签名,如果被修改,签名就会失效。
  • 灵活:token可以支持多种认证方式,例如用户名密码、第三方登录、短信验证码等。token也可以支持多种授权方式,例如基于角色、基于权限、基于范围等。

如何设计token?

一个典型的token由三部分组成:头部(header)、载荷(payload)和签名(signature)。它们之间用点号(.)分隔,例如:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiZXhwIjoxNjE0NzUwNzQ3LCJyb2xlIjoiYWRtaW4ifQ.7y8nZbLh8q1x6rZy7kKlHwv5fXs2fLqk8vVQfYm4c0o
  • 头部(header):包含了token的类型(typ)和使用的算法(alg),通常使用JSON格式,并进行Base64编码。
  • 载荷(payload):包含了用户的信息(sub, name)和其他的声明(exp, role),通常使用JSON格式,并进行Base64编码。
  • 签名(signature):由头部和载荷通过算法(alg)和密钥(secret)生成的散列值,用于验证token的完整性。

如何实现token?

在JAVA语言中,可以使用一些开源的库来实现token的生成和验证,例如jjwt, nimbus-jose-jwt等。以下是一个基于token身份认证的完整实例,它使用了Java语言和Redis数据库。它的主要步骤如下:

  • 在web.xml中配置需要认证的请求,例如/**/userApi/**/**
  • 实现一个过滤器类(AuthFilter),用于拦截需要认证的请求,并调用一个认证类(Author)来验证token。
  • 实现一个认证类(Author),用于从请求头或参数中获取token,并从Redis中获取对应的用户ID。如果用户ID存在,说明token有效,将用户ID存入Redis并放行请求;如果用户ID不存在,说明token无效或过期,拒绝请求并返回错误信息。
  • 实现一个登录接口(LoginController),用于接收用户的用户名和密码,并验证用户的合法性。如果用户合法,生成一个token,并将token和用户ID存入Redis,并返回token给客户端;如果用户不合法,返回错误信息给客户端。
  • 实现一个获取用户信息的接口(UserController),用于根据token从Redis中获取用户ID,并根据用户ID从数据库中获取用户信息,并返回给客户端。

 

以下是相关的代码:

// 导入相关的类
import io.jsonwebtoken.Jwts;
import io.jsonwebtoken.SignatureAlgorithm;
import io.jsonwebtoken.security.Keys;

import java.security.Key;
import java.util.Date;

// 生成一个密钥
Key key = Keys.secretKeyFor(SignatureAlgorithm.HS256);

// 过滤器类
public class AuthFilter implements Filter {
    protected Pattern[] ignorePattern = null;
    PathMatcher matcher = new AntPathMatcher();
    // 不用过滤的请求
    String[] ignoreStrs = null;
    // 需要过滤的请求
    String[] noIgnoreStrs = null;

    public AuthFilter() {
    }

    @Override
    public void destroy() {
    }

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain chain) throws IOException, ServletException {
        HttpServletRequest request = (HttpServletRequest)servletRequest;
        HttpServletResponse response = (HttpServletResponse)servletResponse;
        String uri = request.getRequestURI();
        // 判断是否需要认证
        if (this.checkIgnore(uri) && !this.checkNoIgnore(uri)) {
            chain.doFilter(request, response);
        } else {
            // 用户认证
            Author.checkAuthorLocal(request, response, chain);
        }
    }

    @Override
    public void init(FilterConfig config) throws ServletException {
        String ignore = config.getInitParameter("ignore");
        String noIgnore = config.getInitParameter("noIgnore");
        ignore = StringUtils.defaultIfEmpty(ignore, "");
        this.ignoreStrs = ignore.replaceAll("\\s", "").split(",");
        this.noIgnoreStrs = noIgnore.replaceAll("\\s", "").split(",");
    }

    public boolean checkIgnore(String requestUrl) {
        boolean flag = false;
        String[] var6 = this.ignoreStrs;
        int var5 = this.ignoreStrs.length;
        for(int var4 = 0; var4 < var5; ++var4) {
            String pattern = var6[var4];
            if (flag = this.matcher.match(pattern, requestUrl)) {
                break;
            }
        }
        return flag;
    }

    public boolean checkNoIgnore(String requestUrl) {
        boolean flag = false;
        String[] var6 = this.noIgnoreStrs;
        int var5 = this.noIgnoreStrs.length;
        for(int var4 = 0; var4 < var5; ++var4) {
            String pattern = var6[var4];
            if (flag = this.matcher.match(pattern, requestUrl)) {
                break;
            }
        }
        return flag;
    }
}

// 认证类
public class Author {
    public Author() {
    }

    public static void checkAuthorLocal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        if (!request.getMethod().equals("OPTIONS")) {
            // 获取token
            String token = request.getHeader("oauth_token");
            if (!StringUtil.hasText(token)) {
                token = request.getParameter("oauth_token");
            }
            String loginUserId;
            if (StringUtil.hasText(token)) {
                // 判断token有效性
                loginUserId = getLoginUserId(token);
                if (StringUtil.hasText(loginUserId)) {
                    setLoginUserId(token, loginUserId);
                    chain.doFilter(request, response);
                } else {
                    response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
                    PrintWriter writer = response.getWriter();
                    writer.print("no access");
                    return;
                }
            } else {
                response.setStatus(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
                PrintWriter writer = response.getWriter();
                writer.print("no access");
                return;
            }
        }
    }

    private static String getLoginUserId(String accessToken) {
        String userId = RedisClient.get(accessToken);
        return userId;
    }

    public static void setLoginUserId(String accessToken, String userId) {
        try {
            RedisClient.set(accessToken, userId, Cluster.getTimeoutSecond());
        } catch (Exception var3) {
            var3.printStackTrace();
        }
    }
}
// 登录接口
@RestController
@RequestMapping("/login")
public class LoginController {

    @Autowired
    private UserService userService;

    @PostMapping("/login")
    public Result login(@RequestBody User user) {
        // 验证用户合法性
        User dbUser = userService.findByUsernameAndPassword(user.getUsername(), user.getPassword());
        if (dbUser != null) {
            // 生成token
            String token = Jwts.builder()
                    .setSubject(dbUser.getId()) // 设置用户ID
                    .setExpiration(new Date(System.currentTimeMillis() + 3600000)) // 设置过期时间为1小时
                    .signWith(key) // 使用密钥签名
                    .compact(); // 生成字符串

// 将token和用户ID存入

Redis Author.setLoginUserId(token, dbUser.getId());

// 返回token给客户端

return Result.success(token);

} else {

// 返回错误信息给客户端

return Result.fail(“用户名或密码错误”);

} }

}

 

// 获取用户信息的接口

@RestController @RequestMapping(“/userApi”)

public class UserController {

@Autowired private UserService userService;

@GetMapping(“/getUserInfo”)

public Result getUserInfo(HttpServletRequest request) {

// 根据token从Redis中获取用户ID

String token = request.getHeader(“oauth_token”);

String userId = Author.getLoginUserId(token);

// 根据用户ID从数据库中获取用户信息

User user = userService.findById(userId);

// 返回用户信息给客户端

return Result.success(user);

}

}

 

 

 
  

 

总结

使用token进行身份认证是一种流行的技术,它有无状态、安全和灵活的特点。token由头部、载荷和签名组成,可以使用一些开源的库来实现token的生成和验证。本文介绍了一个基于token身份认证的完整实例,它使用了Java语言和Redis数据库。希望这篇博客对你有所帮助

标签:String,用户,认证,token,ID,public,身份
From: https://www.cnblogs.com/shoshana-kong/p/17523407.html

相关文章

  • ERROR in static/js/*** from UglifyJs Unexpected token: punc (,) [./~/@vant/poppe
     今天打包的时候发现这样的问题,解决方式:找到webpack.base.conf.js文件,加入下边的代码: {test:/\.mjs$/,loader:"babel-loader",include:[resolve("node_modules/@vant/popperjs/dist/index.esm.mjs")]},......
  • springboot+token+redis,模拟登录
    登录测试的controller:loginTest.javapackagecom.example.demo.controller;importcom.example.demo.po.ResponseBean;importorg.springframework.data.redis.core.RedisTemplate;importorg.springframework.web.bind.annotation.*;importjavax.annotation.Resource;i......
  • 基于Sa-Token实现微服务之前的单点登录
    修改配置文件,准备好四个域名127.0.0.1auth.server.com127.0.0.1user.server.com127.0.0.1third.server.com127.0.0.1eureka.server.com注册中心:eureka-server服务pom依赖<dependency><groupId>org.springframework.cloud</groupId>......
  • token(JWT)
    token(JWT)token是服务端生成并返回给HTTP客户端的一串加密字符串,token中保存着用户信息实现会话控制,可以识别用户的身份,主要用于移动端APPtoken的工作流程校验身份,校验通过后响应token,token一般是在响应体中返回给客户端的后续发送请求时,需要手动将token添加在请求报文中......
  • 三个好基友Cookie、Session和Token
    原创声明,转载请注明文章链接来源、作者信息https://mp.weixin.qq.com/s/JGuo0HPAEmcNQMAQ22MhjgCookie、Token和Session区别hello,我是索奇~精心写了一篇Cookie、Session和Token的vivid文章,并分享给大家我们可以把Cookie、Token和Session看作是三个好基友,它们都是用来跟踪用户的身......
  • Csharp的CancellationToken 案例
    usingSystem;usingSystem.Collections.Generic;usingSystem.Linq;usingSystem.Net.Http;usingSystem.Text;usingSystem.Threading;usingSystem.Threading.Tasks;//命名空间namespacepro01{//类internalclassProgram{//main方法......
  • 配置 Git 的用户身份信息
    打开GitBash终端。运行以下命令,将你的邮箱配置为Git的全局默认邮箱(将"[email protected]"替换为你的实际邮箱):gitconfig--globaluser.email"[email protected]"运行以下命令,将你的用户名配置为Git的全局默认用户名(将"YourName"替换为你的实际用户名):gitconf......
  • 企业架构师权威认证—TOGAF® 认证组合中文考试正式上线!
    @所有架构从业人员TOGAF®认证组合中文版考试正式上线啦!  TheOpenGroup亚太区负责人高美华女士进行发布 千呼万唤始出来—TOGAF®认证组合中文版考试正式上线!一直翘首以待中文版考试的朋友们可以开始报名预约啦! 2023年6月29日,在TheOpenGroup主办的「架构·可持续未来峰会......
  • 喜报频传|海泰方圆红莲花安全浏览器喜获国密认证二级证书!
    近日,海泰方圆红莲花安全浏览器成功获得国家密码管理局颁发的安全浏览器密码模块二级产品认证证书!安全浏览器密码模块二级为浏览器产品的最高等级,此证书的取得标志着红莲花安全浏览器整体的安全性得到了进一步的认可,也再一次凸显了海泰方圆强劲的密码能力!经国家密码管理局商用密码检......
  • node使用jsonwebtoken生成token与验证是否过期
    场景我们可以使用cookie,session,token来做鉴权。下面我们来看一下,如何使用token来做鉴权jwt.sign的简单介绍npminstalljsonwebtoken下载使用jsonwebtoken生成token的基本语法。jwt.sign(payload,secretOrPrivateKey,[options,callback])第1个参数payload:可以......