CRM项目通过Filter完成Token验证实现后台登录并验证消息封装信息返回前端------CRM项目

这篇具有很好参考价值的文章主要介绍了CRM项目通过Filter完成Token验证实现后台登录并验证消息封装信息返回前端------CRM项目。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

package com.alatus.web;

import com.alatus.model.TUser;
import com.alatus.result.R;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
//    获取登录信息
    @GetMapping(value = "/api/login/info")
    public R loginInfo(Authentication authentication){
        TUser tUser = (TUser) authentication.getPrincipal();
        return R.OK(tUser);
    }
    //免登录验证
    //因为发送的请求过来首先会过filter那一关,能到这说明token验证都通过了,我们直接返回200即可
    @GetMapping(value = "/api/login/free")
    public R freeLogin(){
        return R.OK();
    }
}
package com.alatus.web;

import com.alatus.model.TUser;
import com.alatus.result.R;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class UserController {
//    获取登录信息
    @GetMapping(value = "/api/login/info")
    public R loginInfo(Authentication authentication){
        TUser tUser = (TUser) authentication.getPrincipal();
        return R.OK(tUser);
    }
    //免登录验证
    //因为发送的请求过来首先会过filter那一关,能到这说明token验证都通过了,我们直接返回200即可
    @GetMapping(value = "/api/login/free")
    public R freeLogin(){
        return R.OK();
    }
}
package com.alatus.result;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

//    封装web层向前端返回的结果
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class R {

    //表示返回的结果码,比如200成功,500失败
    private int code;

    //表示返回的结果信息,比如 用户登录状态失效了,请求参数格式有误.......
    private String msg;

    //表示返回的结果数据,数据可能是一个对象,也可以是一个List集合.....
    private Object data;

    public static R OK() {
        return R.builder()
                .code(CodeEnum.OK.getCode())
                .msg(CodeEnum.OK.getMsg())
                .build();
    }

    public static R OK(int code, String msg) {
        return R.builder()
                .code(code)
                .msg(msg)
                .build();
    }

    public static R OK(Object data) {
        return R.builder()
                .code(CodeEnum.OK.getCode())
                .msg(CodeEnum.OK.getMsg())
                .data(data)
                .build();
    }

    public static R OK(CodeEnum codeEnum) {
        return R.builder()
                .code(CodeEnum.OK.getCode())
                .msg(codeEnum.getMsg())
                .build();
    }

    public static R FAIL() {
        return R.builder()
                .code(CodeEnum.FAIL.getCode())
                .msg(CodeEnum.FAIL.getMsg())
                .build();
    }

    public static R FAIL(String msg) {
        return R.builder()
                .code(CodeEnum.FAIL.getCode())
                .msg(msg)
                .build();
    }

    public static R FAIL(CodeEnum codeEnum) {
        return R.builder()
                .code(codeEnum.getCode())
                .msg(codeEnum.getMsg())
                .build();
    }
}
package com.alatus.result;

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

//    封装web层向前端返回的结果
@Builder
@NoArgsConstructor
@AllArgsConstructor
@Data
public class R {

    //表示返回的结果码,比如200成功,500失败
    private int code;

    //表示返回的结果信息,比如 用户登录状态失效了,请求参数格式有误.......
    private String msg;

    //表示返回的结果数据,数据可能是一个对象,也可以是一个List集合.....
    private Object data;

    public static R OK() {
        return R.builder()
                .code(CodeEnum.OK.getCode())
                .msg(CodeEnum.OK.getMsg())
                .build();
    }

    public static R OK(int code, String msg) {
        return R.builder()
                .code(code)
                .msg(msg)
                .build();
    }

    public static R OK(Object data) {
        return R.builder()
                .code(CodeEnum.OK.getCode())
                .msg(CodeEnum.OK.getMsg())
                .data(data)
                .build();
    }

    public static R OK(CodeEnum codeEnum) {
        return R.builder()
                .code(CodeEnum.OK.getCode())
                .msg(codeEnum.getMsg())
                .build();
    }

    public static R FAIL() {
        return R.builder()
                .code(CodeEnum.FAIL.getCode())
                .msg(CodeEnum.FAIL.getMsg())
                .build();
    }

    public static R FAIL(String msg) {
        return R.builder()
                .code(CodeEnum.FAIL.getCode())
                .msg(msg)
                .build();
    }

    public static R FAIL(CodeEnum codeEnum) {
        return R.builder()
                .code(codeEnum.getCode())
                .msg(codeEnum.getMsg())
                .build();
    }
}
package com.alatus.config;

import com.alatus.config.filter.TokenVerifyFilter;
import com.alatus.config.handler.MyAuthenticationFailureHandler;
import com.alatus.config.handler.MyAuthenticationSuccessHandler;
import com.alatus.config.handler.MyLogoutSuccessHandler;
import com.alatus.constant.Constants;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

@Configuration
public class SecurityConfig {
    @Resource
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
    @Resource
    private MyLogoutSuccessHandler myLogoutSuccessHandler;
    @Resource
    private TokenVerifyFilter tokenVerifyFilter;
//    配置加密器
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Resource
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity,CorsConfigurationSource configurationSource) throws Exception{
        return httpSecurity
                .formLogin((formLogin) -> {
                    formLogin.loginProcessingUrl((Constants.LOGIN_URI))
                            .usernameParameter("loginAct")
                            .passwordParameter("loginPwd")
                            .successHandler(myAuthenticationSuccessHandler)
                            .failureHandler(myAuthenticationFailureHandler);
                })
//        SecurityFilterChain改变了默认行为,不再拦截了,需要手动拦截
                .authorizeHttpRequests((authorize) -> {
//                    对任何请求进行拦截,任何请求都需要登录才可以访问
//                    /api/login这个请求放开,其他请求正常拦截
                    authorize.requestMatchers("/api/login").permitAll().anyRequest().authenticated();
                })
                .csrf((csrf) -> {

                    //禁用跨站请求伪造
                    csrf.disable();
                })
                //支持跨域请求
                .cors((cors)->{
                    cors.configurationSource(configurationSource);
                })
                .sessionManagement((session) -> {
//                    让session的创建策略为不创建
                    session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
                })
//                添加我们自定义的filter
                .addFilterBefore(tokenVerifyFilter, LogoutFilter.class)
//                退出登录
                .logout((logout) -> {
//                    退出的地址,这个也不需要我们写controller
                    logout.logoutUrl("/api/logOut").logoutSuccessHandler(myLogoutSuccessHandler);
                })
                .build();
    }
    @Bean
    public CorsConfigurationSource configurationSource(){
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedOrigins(Arrays.asList("*"));//允许任意来源
        corsConfiguration.setAllowedMethods(Arrays.asList("*"));//允许任意方法请求
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));//允许请求头任意内容
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//        任何路径都按这个来
        source.registerCorsConfiguration("/**",corsConfiguration);
        return source;
    }
}
package com.alatus.config;

import com.alatus.config.filter.TokenVerifyFilter;
import com.alatus.config.handler.MyAuthenticationFailureHandler;
import com.alatus.config.handler.MyAuthenticationSuccessHandler;
import com.alatus.config.handler.MyLogoutSuccessHandler;
import com.alatus.constant.Constants;
import jakarta.annotation.Resource;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.http.SessionCreationPolicy;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.web.authentication.logout.LogoutFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import java.util.Arrays;

@Configuration
public class SecurityConfig {
    @Resource
    private MyAuthenticationSuccessHandler myAuthenticationSuccessHandler;
    @Resource
    private MyLogoutSuccessHandler myLogoutSuccessHandler;
    @Resource
    private TokenVerifyFilter tokenVerifyFilter;
//    配置加密器
    @Bean
    public PasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
    @Resource
    private MyAuthenticationFailureHandler myAuthenticationFailureHandler;
    @Bean
    public SecurityFilterChain securityFilterChain(HttpSecurity httpSecurity,CorsConfigurationSource configurationSource) throws Exception{
        return httpSecurity
                .formLogin((formLogin) -> {
                    formLogin.loginProcessingUrl((Constants.LOGIN_URI))
                            .usernameParameter("loginAct")
                            .passwordParameter("loginPwd")
                            .successHandler(myAuthenticationSuccessHandler)
                            .failureHandler(myAuthenticationFailureHandler);
                })
//        SecurityFilterChain改变了默认行为,不再拦截了,需要手动拦截
                .authorizeHttpRequests((authorize) -> {
//                    对任何请求进行拦截,任何请求都需要登录才可以访问
//                    /api/login这个请求放开,其他请求正常拦截
                    authorize.requestMatchers("/api/login").permitAll().anyRequest().authenticated();
                })
                .csrf((csrf) -> {

                    //禁用跨站请求伪造
                    csrf.disable();
                })
                //支持跨域请求
                .cors((cors)->{
                    cors.configurationSource(configurationSource);
                })
                .sessionManagement((session) -> {
//                    让session的创建策略为不创建
                    session.sessionCreationPolicy(SessionCreationPolicy.STATELESS);
                })
//                添加我们自定义的filter
                .addFilterBefore(tokenVerifyFilter, LogoutFilter.class)
//                退出登录
                .logout((logout) -> {
//                    退出的地址,这个也不需要我们写controller
                    logout.logoutUrl("/api/logOut").logoutSuccessHandler(myLogoutSuccessHandler);
                })
                .build();
    }
    @Bean
    public CorsConfigurationSource configurationSource(){
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.setAllowedOrigins(Arrays.asList("*"));//允许任意来源
        corsConfiguration.setAllowedMethods(Arrays.asList("*"));//允许任意方法请求
        corsConfiguration.setAllowedHeaders(Arrays.asList("*"));//允许请求头任意内容
        UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
//        任何路径都按这个来
        source.registerCorsConfiguration("/**",corsConfiguration);
        return source;
    }
}
package com.alatus.config.handler;

import com.alatus.constant.Constants;
import com.alatus.model.TUser;
import com.alatus.result.CodeEnum;
import com.alatus.result.R;
import com.alatus.service.RedisService;
import com.alatus.util.JSONUtils;
import com.alatus.util.ResponseUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
    @Resource
    private RedisService redisService;
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //用户退出登录,那么把redis中的jwt删除
        TUser tUser = (TUser) authentication.getPrincipal();
//        退出还需要删除redis
        redisService.removeValue(Constants.REDIS_JWT_KEY + tUser.getId());

        //执行到这里,说明退出成功,那我们向前端返回json就行了
        R result = R.OK(CodeEnum.USER_LOG_OUT);

        //把R对象转成json
        String resultJSON = JSONUtils.toJSON(result);

        //把json写出去,写到浏览器
        ResponseUtils.write(response, resultJSON);
    }
}
package com.alatus.config.handler;

import com.alatus.constant.Constants;
import com.alatus.model.TUser;
import com.alatus.result.CodeEnum;
import com.alatus.result.R;
import com.alatus.service.RedisService;
import com.alatus.util.JSONUtils;
import com.alatus.util.ResponseUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;

@Component
public class MyLogoutSuccessHandler implements LogoutSuccessHandler {
    @Resource
    private RedisService redisService;
    @Override
    public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //用户退出登录,那么把redis中的jwt删除
        TUser tUser = (TUser) authentication.getPrincipal();
//        退出还需要删除redis
        redisService.removeValue(Constants.REDIS_JWT_KEY + tUser.getId());

        //执行到这里,说明退出成功,那我们向前端返回json就行了
        R result = R.OK(CodeEnum.USER_LOG_OUT);

        //把R对象转成json
        String resultJSON = JSONUtils.toJSON(result);

        //把json写出去,写到浏览器
        ResponseUtils.write(response, resultJSON);
    }
}
package com.alatus.config.handler;

import com.alatus.constant.Constants;
import com.alatus.model.TUser;
import com.alatus.result.R;
import com.alatus.service.RedisService;
import com.alatus.util.JSONUtils;
import com.alatus.util.JWTUtils;
import com.alatus.util.ResponseUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Resource
    private RedisService redisService;
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //由于禁用了session,我们在登录成功后,需要在服务器保持用户的登录状态,前端下次来访问服务器端的时候,服务器端要知道这个人登录了

        //登录成功,执行该方法,在该方法中返回json给前端,就行了
        TUser tUser = (TUser) authentication.getPrincipal();

        //1、生成jwt
        //把tUser对象转成json作为负载数据放入jwt
        String userJSON = JSONUtils.toJSON(tUser);
        String jwt = JWTUtils.createJWT(userJSON);
        //2、写入redis
        redisService.setValue(Constants.REDIS_JWT_KEY + tUser.getId(), jwt);

        //3、设置jwt的过期时间(如果选择了记住我,过期时间是7天,否则是30分钟)
        String rememberMe = request.getParameter("rememberMe");
        if (Boolean.parseBoolean(rememberMe)) {
            redisService.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.EXPIRE_TIME, TimeUnit.SECONDS);
        } else {
            redisService.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS);
        }

        //登录成功的统一结果
        R result = R.OK(jwt);

        //把R对象转成json
        String resultJSON = JSONUtils.toJSON(result);

        //把R以json返回给前端
        ResponseUtils.write(response, resultJSON);
    }
}
package com.alatus.config.handler;

import com.alatus.constant.Constants;
import com.alatus.model.TUser;
import com.alatus.result.R;
import com.alatus.service.RedisService;
import com.alatus.util.JSONUtils;
import com.alatus.util.JWTUtils;
import com.alatus.util.ResponseUtils;
import jakarta.annotation.Resource;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.TimeUnit;

@Component
public class MyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {
    @Resource
    private RedisService redisService;
    @Override
    public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
        //由于禁用了session,我们在登录成功后,需要在服务器保持用户的登录状态,前端下次来访问服务器端的时候,服务器端要知道这个人登录了

        //登录成功,执行该方法,在该方法中返回json给前端,就行了
        TUser tUser = (TUser) authentication.getPrincipal();

        //1、生成jwt
        //把tUser对象转成json作为负载数据放入jwt
        String userJSON = JSONUtils.toJSON(tUser);
        String jwt = JWTUtils.createJWT(userJSON);
        //2、写入redis
        redisService.setValue(Constants.REDIS_JWT_KEY + tUser.getId(), jwt);

        //3、设置jwt的过期时间(如果选择了记住我,过期时间是7天,否则是30分钟)
        String rememberMe = request.getParameter("rememberMe");
        if (Boolean.parseBoolean(rememberMe)) {
            redisService.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.EXPIRE_TIME, TimeUnit.SECONDS);
        } else {
            redisService.expire(Constants.REDIS_JWT_KEY + tUser.getId(), Constants.DEFAULT_EXPIRE_TIME, TimeUnit.SECONDS);
        }

        //登录成功的统一结果
        R result = R.OK(jwt);

        //把R对象转成json
        String resultJSON = JSONUtils.toJSON(result);

        //把R以json返回给前端
        ResponseUtils.write(response, resultJSON);
    }
}
package com.alatus.result;

import lombok.*;

@Getter
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
public enum CodeEnum {
    OK(200,"成功"),

    FAIL(500,"失败"),

    TOKEN_IS_EMPTY(901,"请求Token参数为空"),

    TOKEN_IS_EXPIRED(902,"Token已过期"),

    TOKEN_IS_ERROR(903,"Token有误"),

    TOKEN_IS_NONE_MATCH(904,"Token信息不合法"),

    USER_LOG_OUT("退出成功");

//    结果码
    private int code;
//    结果信息
    @NonNull
    private String msg;
}
package com.alatus.result;

import lombok.*;

@Getter
@NoArgsConstructor
@RequiredArgsConstructor
@AllArgsConstructor
public enum CodeEnum {
    OK(200,"成功"),

    FAIL(500,"失败"),

    TOKEN_IS_EMPTY(901,"请求Token参数为空"),

    TOKEN_IS_EXPIRED(902,"Token已过期"),

    TOKEN_IS_ERROR(903,"Token有误"),

    TOKEN_IS_NONE_MATCH(904,"Token信息不合法"),

    USER_LOG_OUT("退出成功");

//    结果码
    private int code;
//    结果信息
    @NonNull
    private String msg;
}
package com.alatus.config.filter;

import com.alatus.constant.Constants;
import com.alatus.model.TUser;
import com.alatus.result.R;
import com.alatus.service.RedisService;
import com.alatus.util.JSONUtils;
import com.alatus.util.JWTUtils;
import com.alatus.util.ResponseUtils;
import com.alatus.result.CodeEnum;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import static com.alatus.result.CodeEnum.TOKEN_IS_EXPIRED;


@Component
public class TokenVerifyFilter extends OncePerRequestFilter {

    @Resource
    private RedisService redisService;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (request.getRequestURI().equals(Constants.LOGIN_URI)) { //如果是登录请求,此时还没有生成jwt,那不需要对登录请求进行jwt验证
            //验证jwt通过了 ,让Filter链继续执行,也就是继续执行下一个Filter
            filterChain.doFilter(request, response);
        } else {
            String token = request.getHeader("Authorization");
            if(!StringUtils.hasText("Authorization")){
//                没拿到token,将失败这个枚举传回去,解析并取出常量拼接
                R result = R.FAIL(CodeEnum.TOKEN_IS_EMPTY);
//                封装
                String resultJSON = JSONUtils.toJSON(result);
//                返回
                ResponseUtils.write(response,resultJSON);
                return;
            }
//            验证token有没有被篡改过,也是验证token合法性
            if (!(JWTUtils.verifyJWT(token))){
//                token不合法
                R result = R.FAIL(CodeEnum.TOKEN_IS_NONE_MATCH);
//                封装
                String resultJSON = JSONUtils.toJSON(result);
//                返回
                ResponseUtils.write(response,resultJSON);
                return;
            }
            TUser tUser = JWTUtils.parseUserFromJWT(token);
            String redisToken = (String) redisService.getValue(Constants.REDIS_JWT_KEY + tUser.getId());
            if(!StringUtils.hasText(redisToken)){
//                没有获取到内容说明token过期了
                R fail = R.FAIL(TOKEN_IS_EXPIRED);
                String json = JSONUtils.toJSON(fail);
                ResponseUtils.write(response,json);
                return;
            }
            if (!redisToken.equals(token)) {
//                登陆失败token错误
                R result = R.FAIL(CodeEnum.TOKEN_IS_ERROR);
//                把R对象转为JSON
                String json = JSONUtils.toJSON(result);
                ResponseUtils.write(response,json);
                return;
            }
//            jwt验证通过了
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(tUser,tUser.getLoginPwd(),tUser.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
//            验证jwt通过了,让filter链继续执行
            filterChain.doFilter(request,response);
        }
    }
}
package com.alatus.config.filter;

import com.alatus.constant.Constants;
import com.alatus.model.TUser;
import com.alatus.result.R;
import com.alatus.service.RedisService;
import com.alatus.util.JSONUtils;
import com.alatus.util.JWTUtils;
import com.alatus.util.ResponseUtils;
import com.alatus.result.CodeEnum;
import jakarta.annotation.Resource;
import jakarta.servlet.FilterChain;
import jakarta.servlet.ServletException;
import jakarta.servlet.http.HttpServletRequest;
import jakarta.servlet.http.HttpServletResponse;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import org.springframework.web.filter.OncePerRequestFilter;

import java.io.IOException;
import static com.alatus.result.CodeEnum.TOKEN_IS_EXPIRED;


@Component
public class TokenVerifyFilter extends OncePerRequestFilter {

    @Resource
    private RedisService redisService;
    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
        if (request.getRequestURI().equals(Constants.LOGIN_URI)) { //如果是登录请求,此时还没有生成jwt,那不需要对登录请求进行jwt验证
            //验证jwt通过了 ,让Filter链继续执行,也就是继续执行下一个Filter
            filterChain.doFilter(request, response);
        } else {
            String token = request.getHeader("Authorization");
            if(!StringUtils.hasText("Authorization")){
//                没拿到token,将失败这个枚举传回去,解析并取出常量拼接
                R result = R.FAIL(CodeEnum.TOKEN_IS_EMPTY);
//                封装
                String resultJSON = JSONUtils.toJSON(result);
//                返回
                ResponseUtils.write(response,resultJSON);
                return;
            }
//            验证token有没有被篡改过,也是验证token合法性
            if (!(JWTUtils.verifyJWT(token))){
//                token不合法
                R result = R.FAIL(CodeEnum.TOKEN_IS_NONE_MATCH);
//                封装
                String resultJSON = JSONUtils.toJSON(result);
//                返回
                ResponseUtils.write(response,resultJSON);
                return;
            }
            TUser tUser = JWTUtils.parseUserFromJWT(token);
            String redisToken = (String) redisService.getValue(Constants.REDIS_JWT_KEY + tUser.getId());
            if(!StringUtils.hasText(redisToken)){
//                没有获取到内容说明token过期了
                R fail = R.FAIL(TOKEN_IS_EXPIRED);
                String json = JSONUtils.toJSON(fail);
                ResponseUtils.write(response,json);
                return;
            }
            if (!redisToken.equals(token)) {
//                登陆失败token错误
                R result = R.FAIL(CodeEnum.TOKEN_IS_ERROR);
//                把R对象转为JSON
                String json = JSONUtils.toJSON(result);
                ResponseUtils.write(response,json);
                return;
            }
//            jwt验证通过了
            UsernamePasswordAuthenticationToken authenticationToken = new UsernamePasswordAuthenticationToken(tUser,tUser.getLoginPwd(),tUser.getAuthorities());
            SecurityContextHolder.getContext().setAuthentication(authenticationToken);
//            验证jwt通过了,让filter链继续执行
            filterChain.doFilter(request,response);
        }
    }
}
package com.alatus.util;

import com.alatus.model.TUser;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * jwt工具类
 *
 */
public class JWTUtils {

    public static final String SECRET = "dY8300olWQ3345;1d<3w48";

    /**
     * 生成JWT (token)
     *
     */
    public static String createJWT(String userJSON) {
        //组装头数据
        Map<String, Object> header = new HashMap<>();
        header.put("alg", "HS256");
        header.put("typ", "JWT");

        return JWT.create()
                //头部
                .withHeader(header)

                //负载
                .withClaim("user", userJSON)

                //签名
                .sign(Algorithm.HMAC256(SECRET));
    }

    /**
     * 验证JWT
     *
     * @param jwt 要验证的jwt的字符串
     */
    public static Boolean verifyJWT(String jwt) {
        try {
            // 使用秘钥创建一个JWT验证器对象
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();

            //验证JWT,如果没有抛出异常,说明验证通过,否则验证不通过
            jwtVerifier.verify(jwt);

            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 解析JWT的数据
     *
     */
    public static void parseJWT(String jwt) {
        try {
            // 使用秘钥创建一个验证器对象
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();

            //验证JWT,得到一个解码后的jwt对象
            DecodedJWT decodedJWT = jwtVerifier.verify(jwt);

            //通过解码后的jwt对象,就可以获取里面的负载数据
            Claim nickClaim = decodedJWT.getClaim("nick");
            Claim ageClaim = decodedJWT.getClaim("age");
            Claim phoneClaim = decodedJWT.getClaim("phone");
            Claim birthDayClaim = decodedJWT.getClaim("birthDay");


            String nick = nickClaim.asString();
            int age = ageClaim.asInt();
            String phone = phoneClaim.asString();
            Date birthDay = birthDayClaim.asDate();

            System.out.println(nick + " -- " + age + " -- " + phone + " -- " + birthDay);
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public static TUser parseUserFromJWT(String jwt) {
        try {
            // 使用秘钥创建一个验证器对象
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();

            //验证JWT,得到一个解码后的jwt对象
            DecodedJWT decodedJWT = jwtVerifier.verify(jwt);

            //通过解码后的jwt对象,就可以获取里面的负载数据
            Claim userClaim = decodedJWT.getClaim("user");

            String userJSON = userClaim.asString();

            return JSONUtils.toBean(userJSON, TUser.class);
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}
package com.alatus.util;

import com.alatus.model.TUser;
import com.auth0.jwt.JWT;
import com.auth0.jwt.JWTVerifier;
import com.auth0.jwt.algorithms.Algorithm;
import com.auth0.jwt.exceptions.TokenExpiredException;
import com.auth0.jwt.interfaces.Claim;
import com.auth0.jwt.interfaces.DecodedJWT;

import java.util.Date;
import java.util.HashMap;
import java.util.Map;

/**
 * jwt工具类
 *
 */
public class JWTUtils {

    public static final String SECRET = "dY8300olWQ3345;1d<3w48";

    /**
     * 生成JWT (token)
     *
     */
    public static String createJWT(String userJSON) {
        //组装头数据
        Map<String, Object> header = new HashMap<>();
        header.put("alg", "HS256");
        header.put("typ", "JWT");

        return JWT.create()
                //头部
                .withHeader(header)

                //负载
                .withClaim("user", userJSON)

                //签名
                .sign(Algorithm.HMAC256(SECRET));
    }

    /**
     * 验证JWT
     *
     * @param jwt 要验证的jwt的字符串
     */
    public static Boolean verifyJWT(String jwt) {
        try {
            // 使用秘钥创建一个JWT验证器对象
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();

            //验证JWT,如果没有抛出异常,说明验证通过,否则验证不通过
            jwtVerifier.verify(jwt);

            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 解析JWT的数据
     *
     */
    public static void parseJWT(String jwt) {
        try {
            // 使用秘钥创建一个验证器对象
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();

            //验证JWT,得到一个解码后的jwt对象
            DecodedJWT decodedJWT = jwtVerifier.verify(jwt);

            //通过解码后的jwt对象,就可以获取里面的负载数据
            Claim nickClaim = decodedJWT.getClaim("nick");
            Claim ageClaim = decodedJWT.getClaim("age");
            Claim phoneClaim = decodedJWT.getClaim("phone");
            Claim birthDayClaim = decodedJWT.getClaim("birthDay");


            String nick = nickClaim.asString();
            int age = ageClaim.asInt();
            String phone = phoneClaim.asString();
            Date birthDay = birthDayClaim.asDate();

            System.out.println(nick + " -- " + age + " -- " + phone + " -- " + birthDay);
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }

    public static TUser parseUserFromJWT(String jwt) {
        try {
            // 使用秘钥创建一个验证器对象
            JWTVerifier jwtVerifier = JWT.require(Algorithm.HMAC256(SECRET)).build();

            //验证JWT,得到一个解码后的jwt对象
            DecodedJWT decodedJWT = jwtVerifier.verify(jwt);

            //通过解码后的jwt对象,就可以获取里面的负载数据
            Claim userClaim = decodedJWT.getClaim("user");

            String userJSON = userClaim.asString();

            return JSONUtils.toBean(userJSON, TUser.class);
        } catch (TokenExpiredException e) {
            e.printStackTrace();
            throw new RuntimeException(e);
        }
    }
}
package com.alatus.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JSONUtils {

    //jackson这个jar包转json

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    /**
     * 把java对象转成json
     *
     * @param object
     * @return
     */
    public static String toJSON(Object object) {
        try {
            //把java对象转成json
            return OBJECT_MAPPER.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 把json字符串转java对象
     *
     * @param json
     * @param clazz
     * @return
     * @param <T>
     */
    public static <T> T toBean(String json, Class<T> clazz) {
        try {
            return OBJECT_MAPPER.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
}
package com.alatus.util;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

public class JSONUtils {

    //jackson这个jar包转json

    private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

    /**
     * 把java对象转成json
     *
     * @param object
     * @return
     */
    public static String toJSON(Object object) {
        try {
            //把java对象转成json
            return OBJECT_MAPPER.writeValueAsString(object);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 把json字符串转java对象
     *
     * @param json
     * @param clazz
     * @return
     * @param <T>
     */
    public static <T> T toBean(String json, Class<T> clazz) {
        try {
            return OBJECT_MAPPER.readValue(json, clazz);
        } catch (JsonProcessingException e) {
            throw new RuntimeException(e);
        }
    }
}

文章来源地址https://www.toymoban.com/news/detail-825578.html

到了这里,关于CRM项目通过Filter完成Token验证实现后台登录并验证消息封装信息返回前端------CRM项目的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 在Vue框架项目里通过Element Plus实现表单验证

    最近一直在忙着做项目,在这个过程中也遇到了很多问题,之前虽然也有做笔记总结,但从未发过文章,这是第一次尝试,既为分享,也为记录,写得不好请各位多多指正。 言归正传,相信大家经常都会遇到要处理表单验证的环节,而我在最近的项目中也遇到需要做表单验证

    2024年02月16日
    浏览(29)
  • 安全开发-PHP应用&留言板功能&超全局变量&数据库操作&第三方插件引用&后台模块&Session&Cookie&Token&身份验证&唯一性

    DW + PHPStorm + PhpStudy + Navicat Premium DW : HTMLJSCSS开发 PHPStorm : 专业PHP开发IDE PhpStudy :Apache MYSQL环境 Navicat Premium: 全能数据库管理工具 1、数据库名,数据库表名,数据库列名 2、数据库数据,格式类型,长度,键等 PHP函数:连接,选择,执行,结果,关闭等 参考:https://www.runoo

    2024年02月17日
    浏览(40)
  • Jwt(Json web token)——使用token的权限验证方法 & 用户+角色+权限表设计 & SpringBoot项目应用

    1.认证鉴权服务,注册中心,认证中心,鉴权中心; 2.用户,角色,权限表设计,数据库视图的使用; 3.项目中的应用,使用自定义注解+拦截器; 4.枚举类型的json化, @JsonFormat(shape = JsonFormat.Shape.OBJECT) @Getter https://gitee.com/pet365/springboot-privs-token 用户和权限之间关系(多对多

    2024年02月14日
    浏览(38)
  • CSS通过设置filter实现元素交融效果

    2024年02月15日
    浏览(27)
  • GateWay网关自定义过滤器实现token校验完成统一鉴权

    gateWay---API网关,也可以称为业务网关,主要服务于微服务的; (1)  三大组件 路由(Route)         构建网关的基本模块,由id(唯一标示)、目标URI、一组断言、一组过滤器组成,如果断言为true,则匹配该路由   断言(Predicate)          可以使用它匹配来自HTTP请求的任何

    2024年02月08日
    浏览(37)
  • 使用JWT生成token实现权限验证

            点击登录按钮,后端验证账号密码是否通过,如果通过则生成token,把token发送给前端,前端保存到cookie(前后端分离是不能使用保存session,因为每次发送ajax请求响应后都会断开服务器,就会导致session生命周期就销毁掉,然后再发送请求时再重新连接服务器,s

    2023年04月08日
    浏览(32)
  • 解决:Hbuilder工具点击发行打包,一直报尚未完成社区身份验证,请点击链接xxxxx,项目xxx发布H5失败的错误。[Error]尚未完成社区身份验证

    全世界任何漂亮有魅力的女生,都不会因为你送她汉堡或奶茶而对你说我爱你,明白吗?你应该带她做一些特别的事情,让她感动。 [Error]尚未完成社区身份验证,请点击链接 https://ask.dcloud.net.cn/account/setting/profile 验证后再重新打包。如果验证后仍然提示此信息,请检查HBui

    2024年02月12日
    浏览(55)
  • SpringBoot集成JWT token实现权限验证

    先在pom中引入 JWT依赖 然后引入一个生成的 token 的工具类         然后具体实现上有两种方式,一个是使用自定义注解配合拦截器,另外一个是使用拦截器。 方法一:         先自定义个注解,然后再定义一个自定义拦截器 JwtInterceptor 类,同时让 JwtInterceptor 类继承

    2024年02月10日
    浏览(34)
  • 实现前后端分离的登陆验证token思路

    在前后端完全分离的情况下,Vue项目中实现token验证大致思路如下: 1、第一次登录的时候,前端调后端的登陆接口,发送用户名和密码 2、后端收到请求,验证用户名和密码,验证成功,就给前端返回一个token 3、前端拿到token,将token存储到localStorage和vuex中,并跳转路由页面

    2024年02月03日
    浏览(29)
  • 当我再次用Kotlin完成五年前已经通过Kotlin完成的项目后

      近日来对Kotlin的使用频率越来越高, 也对自己近年来写过的Kotlin代码尝试进行一个简单的整理. 翻到了自己五年前第一次使用Kotlin来完成的一个项目([贝塞尔曲线](https://juejin.cn/post/6844903556173004807)), 一时兴起, 又用发展到现在的Kotlin和Compose再次完成了这个项目. 也一遍来看看

    2024年02月03日
    浏览(23)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包