登录验证Jwt令牌,过滤器,拦截器

jwt令牌有三个部分,第一部分是令牌名,然后数据名,最后加密数据。前两个使用了64个字母代替加密,第三个用算法对前两个就行加密,只有jwt解密算法才能解。

然后登录验证的逻辑是:

如果客户没登陆的情况下访问非login页面,就会强行跳转到登录页面。

登录成功后返回一个加密jwt,前端保存到本地,每次使用add,del,sel时,将数据放在请求头中传到后端。

后端用一个拦截器,login放过,直接去验证登录,其他的路径就验证jwt令牌,没有或者不合法全部拦截下来,返回前端错误提示。

登录代码:

   @RequestMapping("/login")
    public ReturnData login(String name, String pwd) {
        QueryWrapper<User> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("name", name);
        queryWrapper.eq("pwd", pwd);
        User user = userMapper.selectOne(queryWrapper);
        if (user != null) {
            HashMap<String, Object> map = new HashMap<>();
            map.put("name", name);
            map.put("pwd", pwd);
            JwtUtil jwtUtil = new JwtUtil();
            String lingpai = jwtUtil.getJwt(map, 12);
            return new ReturnData(1, "1", lingpai);
        }
        return new ReturnData(0, "账户或密码错误", null);
    }

过滤器:(过滤会有一个跨域问题,得设置一下)

package com.quxiao.controller;

import com.quxiao.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Map;

/**
 * @program: SpringBoot4
 * @author: quxiao
 * @create: 2023-04-22 17:20
 **/
@Slf4j
@WebFilter(urlPatterns = "/*")
public class CheckFilter implements Filter {
    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        HttpServletRequest httpServletRequest = (HttpServletRequest) servletRequest;
        HttpServletResponse httpServletResponse = (HttpServletResponse) servletResponse;
        httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");  // 允许跨域的地址为所有
        httpServletResponse.addHeader("Access-Control-Max-Age", "3600");  // 非简单请求,只要第一次通过OPTIONS检查 在1小时之内不会在调用OPTIONS进行检测
        httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
        String tock = httpServletRequest.getHeader("tock");
        String s = httpServletRequest.getRequestURL().toString();
        //为登录
        if (s.contains("login")) {
            filterChain.doFilter(servletRequest, servletResponse);
        } else {
            //不为登录,判断令牌
            if (tock != null && tock.length() != 0) {
                JwtUtil jwtUtil = new JwtUtil();
                //判断令牌有安全性
                if (jwtUtil.checkJwt(tock)) {
                    filterChain.doFilter(servletRequest, servletResponse);
                } else {
                    log.info("令牌安全性有误");
                }
            } else {
                //无令牌,没登陆
                servletResponse.getWriter().write("NOT_LOGIN");
            }
        }
    }
}

拦截器:

package com.quxiao.controller.Interceptor;

import com.quxiao.util.JwtUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

/**
 * @program: SpringBoot4
 * @author: quxiao
 * @create: 2023-04-23 09:18
 **/
@Component
@Slf4j
public class LoginCheckInterceptor implements HandlerInterceptor {
    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object handler) throws Exception {
        httpServletResponse.setHeader("Access-Control-Allow-Origin", "*");  // 允许跨域的地址为所有
        httpServletResponse.addHeader("Access-Control-Max-Age", "3600");  // 非简单请求,只要第一次通过OPTIONS检查 在1小时之内不会在调用OPTIONS进行检测
        httpServletResponse.setHeader("Access-Control-Allow-Credentials", "true");
        String tock = httpServletRequest.getHeader("tock");
        String s = httpServletRequest.getRequestURL().toString();
        //为登录
        if (s.contains("login")) {
            return true;
        } else {
            //不为登录,判断令牌有效性
            if (tock != null && tock.length() != 0) {
                JwtUtil jwtUtil = new JwtUtil();
                //判断令牌有安全性
                if (jwtUtil.checkJwt(tock)) {
                    return true;
                } else {
                    log.info("令牌安全性有误");
                }
            } else {
                //无令牌,没登陆
                httpServletResponse.getWriter().write("{\"code\":0,\"msg\":0,\"data\":\"NOT_LOGIN\"}");
            }
        }
        return false;
    }

    @Override
    public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
        System.out.println("准备返回前端");
    }

    @Override
    public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception {
        System.out.println("全部完成了");
    }
}

将拦截器交给Spring使用管理,加载配置:

package com.quxiao.config;

import com.quxiao.controller.Interceptor.LoginCheckInterceptor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.InterceptorRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;

/**
 * @program: SpringBoot4
 * @author: quxiao
 * @create: 2023-04-23 09:21
 **/
//@Configuration
public class WebConfig implements WebMvcConfigurer {
    @Autowired
    LoginCheckInterceptor loginCheckInterceptor;

    @Override
    public void addInterceptors(InterceptorRegistry registry) {
        registry.addInterceptor(loginCheckInterceptor).addPathPatterns("/**").excludePathPatterns("/login");
    }
}

过滤器在拦截器前面执行。

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
首先,需要了解什么是拦截器JWT拦截器是一个在请求处理之前或之后进行拦截拦截的组件,类似于过滤器,可以对请求进行预处理、后处理等。在 Spring 框架中,可以使用拦截器来实现一些通用的处理逻辑,例如身份验证、日志记录等。 JWT(JSON Web Token)是一种用于身份验证的标准,它可以在用户和服务器之间传递安全可靠的信息,并且不需要在服务器端存储用户的信息。JWT 由三部分组成:头部、载荷和签名。头部包含加密算法和类型,载荷包含用户信息和过期时间等,签名用于验证数据的完整性和真实性。 接下来,我们来实现自定义拦截器JWT 身份验证。 1. 创建 Auth0 账号并创建应用 在 Auth0 官网注册账号并创建一个应用,获取应用的客户端 ID 和客户端密钥。 2. 添加 Auth0 Spring Security 集成依赖 在 Maven 或 Gradle 中添加 Auth0 Spring Security 集成依赖,以 Maven 为例: ```xml <dependency> <groupId>com.auth0</groupId> <artifactId>auth0-spring-security-api</artifactId> <version>1.5.0</version> </dependency> ``` 3. 创建 JWTUtils 工具类 在项目中创建 JWTUtils 工具类,用于生成和解析 JWT。 ```java import com.auth0.jwt.JWT; import com.auth0.jwt.algorithms.Algorithm; import com.auth0.jwt.interfaces.DecodedJWT; import java.util.Date; public class JWTUtils { private static final long EXPIRE_TIME = 30 * 60 * 1000; // 过期时间,单位毫秒 private static final String TOKEN_SECRET = "secret"; // 密钥 /** * 生成 token * * @param userId 用户 ID * @return token */ public static String createToken(String userId) { Date expireAt = new Date(System.currentTimeMillis() + EXPIRE_TIME); return JWT.create() .withIssuer("auth0") .withClaim("userId", userId) .withExpiresAt(expireAt) .sign(Algorithm.HMAC256(TOKEN_SECRET)); } /** * 验证 token * * @param token token * @return 用户 ID */ public static String verifyToken(String token) { DecodedJWT jwt = JWT.require(Algorithm.HMAC256(TOKEN_SECRET)) .withIssuer("auth0") .build() .verify(token); return jwt.getClaim("userId").asString(); } } ``` 4. 创建 Auth0Config 配置类 在项目中创建 Auth0Config 配置类,用于配置 Auth0 的参数。 ```java import com.auth0.spring.security.api.JwtWebSecurityConfigurer; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; @Configuration @EnableWebSecurity public class Auth0Config { @Value(value = "${auth0.apiAudience}") private String apiAudience; @Value(value = "${auth0.issuer}") private String issuer; /** * 配置 Auth0 参数 */ public void configure(HttpSecurity http) throws Exception { JwtWebSecurityConfigurer.forRS256(apiAudience, issuer) .configure(http) .authorizeRequests() .antMatchers("/api/public/**").permitAll() .anyRequest().authenticated(); } } ``` 5. 创建 Auth0Interceptor 拦截器 在项目中创建 Auth0Interceptor 拦截器,用于拦截请求并进行身份验证。 ```java import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @Component public class Auth0Interceptor implements HandlerInterceptor { @Autowired private Auth0Client auth0Client; @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { String authorizationHeader = request.getHeader("Authorization"); if (authorizationHeader != null && authorizationHeader.startsWith("Bearer ")) { String token = authorizationHeader.substring(7); String userId = JWTUtils.verifyToken(token); if (userId != null) { request.setAttribute("userId", userId); return true; } } response.setStatus(401); return false; } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { } @Override public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler, Exception ex) throws Exception { } } ``` 6. 创建 Auth0Client 客户端 在项目中创建 Auth0Client 客户端,用于与 Auth0 进行交互,例如获取用户信息等。 ```java import com.auth0.client.auth.AuthAPI; import com.auth0.client.mgmt.ManagementAPI; import com.auth0.exception.Auth0Exception; import com.auth0.json.auth.TokenHolder; import com.auth0.json.mgmt.users.User; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; @Component public class Auth0Client { @Value(value = "${auth0.domain}") private String domain; @Value(value = "${auth0.clientId}") private String clientId; @Value(value = "${auth0.clientSecret}") private String clientSecret; /** * 获取访问令牌 * * @return 访问令牌 * @throws Auth0Exception Auth0 异常 */ public String getAccessToken() throws Auth0Exception { AuthAPI authAPI = new AuthAPI(domain, clientId, clientSecret); TokenHolder tokenHolder = authAPI.requestToken("https://" + domain + "/api/v2/"); return tokenHolder.getAccessToken(); } /** * 根据用户 ID 获取用户信息 * * @param userId 用户 ID * @return 用户信息 * @throws Auth0Exception Auth0 异常 */ public User getUserById(String userId) throws Auth0Exception { ManagementAPI managementAPI = new ManagementAPI(domain, getAccessToken()); return managementAPI.users().get(userId, null).execute(); } } ``` 7. 配置拦截器和认证管理器 在 Spring 配置文件中配置拦截器和认证管理器。 ```xml <!-- 配置拦截器 --> <mvc:interceptor> <mvc:mapping path="/api/**"/> <bean class="com.example.demo.interceptor.Auth0Interceptor"/> </mvc:interceptor> <!-- 配置认证管理器 --> <bean class="org.springframework.security.authentication.AuthenticationManager"/> ``` 8. 创建登录和登出接口 在控制器中创建登录和登出接口,用于生成和验证 JWT。 ```java import com.auth0.exception.Auth0Exception; import com.auth0.json.mgmt.users.User; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; @RestController @RequestMapping("/api/auth") public class AuthController { @Autowired private Auth0Client auth0Client; /** * 登录接口 * * @param username 用户名 * @param password 密码 * @return token * @throws Auth0Exception Auth0 异常 */ @PostMapping("/login") public String login(@RequestParam String username, @RequestParam String password) throws Auth0Exception { // 根据用户名和密码验证用户身份,并获取用户 ID String userId = "user123"; return JWTUtils.createToken(userId); } /** * 登出接口 */ @PostMapping("/logout") public void logout() { // 清除 token } } ``` 以上就是使用自定义拦截器和 Auth0 JWT 实现登录、登出的步骤。通过这种方式,可以实现简单、安全、可靠的用户身份验证,有效地保护用户的数据安全。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值