精华内容
下载资源
问答
  • Token 一定要放在请求头中吗...Token 解析过程说明当我们使用 spring security oauth2 时, 一般情况下需要把认证中心申请 token 放在请求头中请求目标接口,如下图 ① spring security oauth2 通过拦截器获取此 t...

    Token 一定要放在请求头中吗? 答案肯定是否定的,本文将从源码的角度来分享一下 spring security oauth2 的解析过程,及其扩展点的应用场景。

    Token 解析过程说明

    当我们使用 spring security oauth2 时, 一般情况下需要把认证中心申请的 token 放在请求头中请求目标接口,如下图 ①

    821d05a23afe19491432d794d87ec40a.png

    spring security oauth2 通过拦截器获取此 token 完成令牌到当前用户信息(UserDetails)的转换。

    OAuth2AuthenticationProcessingFilter.doFilter

    public class OAuth2AuthenticationProcessingFilter{

    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException,

    ServletException {

    try {

    // 1. 根据用户请求解析令牌,组装预登陆对象

    Authentication authentication = tokenExtractor.extract(request);

    if (authentication == null) {

    // 若是预登陆状态为空,把无状态登录清空

    if (stateless && isAuthenticated()) {

    SecurityContextHolder.clearContext();

    }

    }

    else {

    // 2. 根据token 来做真正的认证登录 Provier

    Authentication authResult = authenticationManager.authenticate(authentication);

    // 3. 登录成功逻辑

    eventPublisher.publishAuthenticationSuccess(authResult);

    SecurityContextHolder.getContext().setAuthentication(authResult);

    }

    }

    catch (OAuth2Exception failed) {

    // 异常通知逻辑 Spring Event

    ...

    return;

    }

    chain.doFilter(request, response);

    }

    }

    我们主要来关注第一步 根据用户请求解析令牌,组装预登陆对象

    来看默认实现 BearerTokenExtractor

    public class BearerTokenExtractor implements TokenExtractor {

    @Override

    public Authentication extract(HttpServletRequest request) {

    // 1. 解析token

    String tokenValue = extractToken(request);

    if (tokenValue != null) {

    // 2. 创建一个authentication 返回

    PreAuthenticatedAuthenticationToken authentication = new PreAuthenticatedAuthenticationToken(tokenValue, "");

    return authentication;

    }

    return null;

    }

    protected String extractToken(HttpServletRequest request) {

    // 1.1 优先从请求header 获取token

    String token = extractHeaderToken(request);

    // 1.2 若是请求token 中没有,则获取请求参数中的 access_token 参数

    if (token == null) {

    token = request.getParameter(OAuth2AccessToken.ACCESS_TOKEN);

    }

    return token;

    }

    }

    扩展点

    丰富获取 token 渠道,个性化处理.例如掘金的 X-Legacy-Token 而非必须是 Authorization

    d73569f3fc0c0061065142f8c6070422.png

    请求参数中携带 access_token 参数也能被正确解析处理

    a57233e47544157798ba767653d338f4.png

    重写 BearerTokenExtractor 解决,若请求携带 token 无论接口是否被设置 permitAll 都会被拦截判断的问题

    c968cc34eea4d914269b9290e11f909e.png

    展开全文
  • 但是token校验重构完之后出问题了,之前写filter走是springgateway,基于GatewayFilter实现,重构了之后基于filter,然后当请求进入过滤器时候,发现不能获取到请求自定义请求头。String token = request....

    有个钱包项目,本来用的是微服务这一套,后来感觉没必要,重构成了简单的springboot项目,但是token校验重构完之后出问题了,之前写filter走的是springgateway,基于GatewayFilter实现,重构了之后基于filter,然后当请求进入过滤器的时候,发现不能获取到请求的自定义请求头。

    String token = request.getHeader("token"); // null

    String id = request.getHeader("id"); // null

    String role = request.getHeader("role"); // null

    原因

    我在进入断点的时候查看了一下servletRequest,发现请求方法是options。 我知道get post delete put。还真不了解options,百度了下。主要参考这篇文章。原来是浏览器的同源策略问题,也就是cors,可我一想,我配置了cors啊

    @Configuration

    public class CorsConfig {

    private CorsConfiguration buildConfig() {

    CorsConfiguration corsConfiguration = new CorsConfiguration();

    corsConfiguration.addAllowedOrigin("*"); // 1

    corsConfiguration.addAllowedHeader("*"); // 2

    corsConfiguration.addAllowedMethod("*"); // 3

    return corsConfiguration;

    }

    @Bean

    public CorsFilter corsFilter() {

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource();

    source.registerCorsConfiguration("/**", buildConfig()); // 4

    return new CorsFilter(source);

    }

    }

    怎么还报跨域的问题呢,想起来了我的tokenFilter里因为拿不到请求头token,我抛出了参数异常,然后@RestControllerAdvice跟@ExceptionHandle处理不了filter中抛出的异常,导致程序报500错误,然后过滤器是类似于切面的 么,这里断了导致返回头也没加上。

    处理

    怎么处理浏览器发过来的预处理 options请求呢,太懒了,直接这样写了

    HttpServletRequest request= (HttpServletRequest)servletRequest;

    HttpServletResponse res = (HttpServletResponse) servletResponse;

    String method=request.getMethod();

    if(HttpMethod.OPTIONS.toString().equals(method)){

    res.setStatus(HttpStatus.NO_CONTENT.value());

    }else {

    String token = request.getHeader("token");

    String id = request.getHeader("id");

    String role = request.getHeader("role");

    ~~~~~~~

    回想

    我记得我上个项目也没处理options请求啊,怎么没报cors问题啊,对了我记得我在nginx处理过了

    if ($request_method = 'OPTIONS') {

    return 204;

    }

    add_header Access-Control-Allow-Origin * always;

    add_header Access-Control-Allow-Headers "Content-Type, Authorization" always;

    add_header Access-Control-Allow-Methods "GET, POST, OPTIONS, PUT, PATCH, DELETE, HEAD" always;

    add_header Access-Control-Max-Age 86400 always;

    原来自己又写前端,也写后端,怎么这些问题还能碰到呢,:relieved:,前辈们都写好了,自己还没遇到问题也没深入过,还有springcloud里面的corsWebFilter怎么就跟springboot里面的corsFilter不一样呢。

    @Configuration

    public class CorsConfig {

    @Bean

    public CorsWebFilter corsFilter() {

    CorsConfiguration config = new CorsConfiguration();

    config.addAllowedMethod("*");

    config.addAllowedOrigin("*");

    config.addAllowedHeader("*");

    UrlBasedCorsConfigurationSource source = new UrlBasedCorsConfigurationSource(new PathPatternParser());

    source.registerCorsConfiguration("/**", config);

    return new CorsWebFilter(source);

    }

    }

    还是得多看源码啊,我这个crudboy

    总结

    以上所述是小编给大家介绍的springboot使用filter获取自定义请求头的实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!

    展开全文
  • 场景:过滤器中获取参数Token并添加到请求头(用户认证兼容老系统)请求头和请求参数是不能直接修改,也没有提供修改方法,但是可以在过滤器和拦截器使用HttpServletRequestWrapper包装类达到修改目的。...

    场景:过滤器中获取参数Token并添加到请求头(用户认证兼容老系统)

    请求头和请求参数是不能直接修改,也没有提供修改的方法,但是可以在过滤器和拦截器中使用HttpServletRequestWrapper包装类达到修改的目的。

    一、实现HttpServletRequestWrapper接口,下面直接使用匿名类

    package com.xxxx.web.filter;

    import org.apache.commons.lang3.StringUtils;

    import javax.servlet.*;

    import javax.servlet.annotation.WebFilter;

    import javax.servlet.http.HttpServletRequest;

    import javax.servlet.http.HttpServletRequestWrapper;

    import java.io.IOException;

    import java.util.Enumeration;

    @WebFilter

    public class AuthHeaderSettingFilter implements Filter{

    @Override

    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {

    HttpServletRequestWrapper requestWrapper = new HttpServletRequestWrapper((HttpServletRequest) request) {

    /**

    * 当调用request.getHeader("token")时,则获取请求参数中token值并当做Header的值返回

    * @param name

    * @return

    */

    @Override

    public String getHeader(String name) {

    // 先从原本的Request中获取头,如果为空且名字为token,则从参数中查找并返回

    String superHeader = super.getHeader(name);

    if("token".equals(name) && StringUtils.isEmpty(superHeader)){

    String token = request.getParameter("token");

    if (StringUtils.isNotEmpty(token)) {

    return token ;

    }

    }

    return superHeader;

    }

    };

    chain.doFilter(requestWrapper,response);

    }

    @Override

    public void destroy() {

    }

    }

    二、HttpServletRequestWrapper、ServletRequestWrapper和HttpServletRequest接口中的很多方法都可以重写

    要想增加一个请求参数可以在HttpServletRequestWrapper中重写getParameter(String name)

    @Override

    public String getParameter(String name) {

    if("newParam".equals(name)){

    return "这是我新增加的参数";

    }

    return super.getParameter(name);

    }

    @Override

    public Map getParameterMap() {

    HashMap newMap = new HashMap<>();

    newMap.putAll(super.getParameterMap());

    newMap.put("newParam",new String[]{"这是我新增加的参数"}) ;

    return Collections.unmodifiableMap(newMap);

    }

    @Override

    public String[] getParameterValues(String name) {

    if("newParam".equals(name)){

    return new String[]{"这是我新增加的参数"};

    }

    return super.getParameterValues(name);

    }

    注意: getParameterMap()返回的时一个不可修改的map ,不能直接向里面put值, 所以在重写这个方法时要自己new 一个HashMap ,然后在新建的map中放值,最后返回时必须调用Collections.unmodifiableMap(Map extends K, ? extends V> m) 把map改成不可变的

    结构

    a8c9d45775ea

    image.png

    a8c9d45775ea

    image.png

    参考:

    展开全文
  • Java Token登录验证 生成解析Token

    千次阅读 2020-06-05 22:32:59
    当用户第一次登陆后,用户名密码验证成功后,服务器会生成一个token,把token返回到客户端,一般token都是储存在浏览器的localStorage 或 cookies中,存在localStorage的token需要通过js,将token添加到http请求头中,...

    借鉴参考

    Java Token登录验证 使用jjwt生成和解析JWT
    java基于token验证之登陆验证

    什么是Token?

    我的理解来说 token就是你访问服务器的口令,只要token合法,正确,你就能获取到后端数据

    当用户第一次登陆后,用户名密码验证成功后,服务器会生成一个token,把token返回到客户端,一般token都是储存在浏览器的localStorage 或 cookies中,存在localStorage的token需要通过js,将token添加到http请求头中,下次再访问服务器,就不需要用户名密码了,只要带上token,服务器验证token的合法性后,就能访问后端资源了。是不是觉的很方便

    添加依赖

    我的项目是用gradle构建的,maven添加依赖可以百度一下
    implementation (“io.jsonwebtoken:jjwt:0.9.0”)
    implementation (“com.auth0:java-jwt:3.4.0”)

    我前端是vue.js 用了element ui 三方库,servlet,mybatis

    参考了链接

    public class TokenSign {
        /**
         * @author
         * 设置过期时间 1小时钟 为了方便测试
         * 设置Token密匙 最好长一点
         */
        private static final long EXPIRE_TIME= 60 * 60 * 1000;
        private static final String TOKEN_SECRET="Token";
        /**
         * 产生token
         * @param useName
         * @param userId
         * @return
         */
        public static String Sign(String useName , long userId){
            try{
            	//这里将useName 和 userId 存入了Token,在下面的解析中,也会有解析的方法可以获取到Token里面的数据
                //Token过期的时间 
                Date date = new Date(System.currentTimeMillis()+EXPIRE_TIME);
                System.out.println("date"+date);
                Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
    
                //设置头部信息
                Map<String,Object> header = new HashMap<>();
                header.put("typ","JWT");
                header.put("alg","HS256");
    
                //附带username和userid信息,存储到token中,生成签名
                return JWT.create()
                        .withHeader(header)
    
                        //存储自己想要留存给客户端浏览器的内容
                        .withClaim("userName",useName)
                        .withClaim("userId",userId)
                        .withExpiresAt(date)
                        .sign(algorithm);
            }catch (Exception e){
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * token校验是否正确
         * @param token
         * @return
         */
    
        public static boolean verify(String token){
            try{
                Algorithm algorithm = Algorithm.HMAC256(TOKEN_SECRET);
    
                JWTVerifier verifier = JWT.require(algorithm).build();
    
                DecodedJWT decodedJWT = verifier.verify(token);
    
                return true;
    
            }catch (Exception e){
                System.out.println("Token超时,需要重新登录");
            }
    
            return false;
        }
    
        /**
         * 获取token中信息 userName
         * @param token
         * @return
         */
    
        public static String getUsername(String token){
            try {
                DecodedJWT jwt = JWT.decode(token);
                return jwt.getClaim("userName").asString();
    
            }catch (JWTDecodeException e){
                e.printStackTrace();
            }
            return null;
        }
    
        /**
         * 获取token中信息 userId
         * @param token
         * @return
         */
    
        public static Long getUserId(String token){
            try{
                DecodedJWT jwt = JWT.decode(token);
                return jwt.getClaim("userId").asLong();
            }catch (JWTDecodeException e){
                e.printStackTrace();
            }
            return null;
        }
    
    }
    

    前端收到的数据
    Response中的Token
    储存到localStorage中的token
    储存到localStorage中的token

    请求头添加Token

    在main.js 中添加拦截器,添加请求头在这里插入图片描述

    axios.interceptors.request.use(config => {
    	// 为请求头添加Authorization字段为服务端返回的token
    	config.headers.Authorization = localStorage.getItem('token')
    	return config
      })
    

    这样的话请求头添加了token
    在这里插入图片描述

    过滤器

    @WebFilter注解详情
    这里的urlPatterns填路径
    如果我的 @WebServlet("/Jwt/JwtListTest") 是这样的 WebServlet就能过滤下掉
    如果我的 @WebServlet("/sadasda/JwtListTest") 是这样的 WebServlet就不能过滤 TheInterceptor就不会执行

    @WebFilter(filterName = "TheInterceptor",urlPatterns = {"/jwt/*"})
    public class TheInterceptor implements Filter {
        //初始化
        @Override
        public void init(FilterConfig filterConfig) throws ServletException {
            System.out.println("Filter初始化");
        }
    
    
        @Override
        public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
            System.out.println("doFilter");
            HttpServletRequest req = (HttpServletRequest) request;
            HttpServletResponse resp = (HttpServletResponse) response;
            request.setCharacterEncoding("UTF-8");
            response.setCharacterEncoding("UTF-8");
            response.setContentType("text/html;charset=utf-8");
            ObjectNode objectNode=new ObjectNode(JsonNodeFactory.instance); //初始化json对象
            PrintWriter out = response.getWriter();
    
            String url = req.getServletPath();
    
    		//获取请求头Authorization字段的数据
            String token = req.getHeader("Authorization");
    
            boolean result = false;
            /**
             * 1001 token不存在,先登录
             * 1002 token存在,但是token不合法
             *
             * 2000 用户名或密码错误
             * 2999 登陆成功
             * 2998 注销登录成功
             * 2997 注销登录失败
             *
             * 3000 用户注册失败
             * 3001 用户名重复
             * 3999 用户注册成功
             *
             * 3002 用户信息更新成功
             * 3998 用户信息更新失败
             */
            //如果url 复合 这些,直接放行,不用验证token
            if (
                    "/jwt/JwtLogin".equalsIgnoreCase(url) ||
                            "/jwt/JwtRegister".equalsIgnoreCase(url) ||
                                "/jwt/JwtOrderDetail".equalsIgnoreCase(url) ||
                                        "/Jwt/JwtListTest".equalsIgnoreCase(url)){
                System.out.println("if语句执行了");
                chain.doFilter(request, response);//这是放行的语句
            }else {
                /**
                 * 如果不是,登录界面,注销界面,注册界面 则执行以下语句
                 * 如果 要去商品界面,购物车界面等需要,登录状态的界面,
                 * 如果token==null 说明 没有登录,数据返回前端,让前端进行跳转到登录界面登录
                 * 如果token !== null 先进行token合法性的验证
                 * 如果token 不合法,数据返回前端,让前端进行跳转到登录界面登录,合法则让请求,去到相应界面
                 */
                if (token == null){  //如果token存在 则执行放行
                    System.out.println("token不存在");
                    objectNode.put("status",1001);
                    out.println(objectNode);
                    out.close();
                }else {
                    //如果是不空,说明登陆过,先判断token合法性(也包括了对token时效性的判断)
                    result = TokenSign.verify(token);
                    if (result){
                        System.out.println("token合法");
                        try {
                            chain.doFilter(request, response);
                        }catch (Exception e){
                            System.out.println("chain.doFilter报错");
                            e.printStackTrace();
                        }
                        System.out.println("token合法1");
                    }else {
                        System.out.println("token不合法");
                        objectNode.put("status",1002);
                        out.println(objectNode);
                        out.close();
                    }
    
                }
            }
    
        }
    
        @Override
        public void destroy() {
            System.out.println("Filter摧毁");
        }
    }
    

    这篇博客借鉴参考很多,主要为了是加深自己的记忆,希望各位大牛不要见笑,如果有错误请告知

    基于Token的WEB后台认证机制
    Java实现基于token认证

    展开全文
  • 每一个请求我都需要在请求头里面加上token这个请求头,作为一种校验机制,传统的接口可以通过设置一个全局的变量,然后通过页面携带过来(大概就是先将我们的token放在session中,写一个服务用来获取session中的...
  • 每一个请求我都需要在请求头里面加上token这个请求头,作为一种校验机制,传统的接口可以通过设置一个全局的变量,然后通过页面携带过来(大概就是先将我们的token放在session中,写一个服务用来获取session中的...
  • 场景:过滤器中获取参数Token并添加到请求头(用户认证兼容老系统) 请求头和请求参数是不能直接修改,也没有提供修改方法,但是可以在过滤器和拦截器使用HttpServletRequestWrapper包装类达到修改目的。 ...
  • 场景:过滤器中获取参数Token并添加到请求头(用户认证兼容老系统)请求头和请求参数是不能直接修改,也没有提供修改方法,但是可以在过滤器和拦截器使用HttpServletRequestWrapper包装类达到修改目的。...
  • java关于https使用代理进行连接 问题描述 ...//设置请求头属性,请求token不需要带额外参数时使用 public static Map<String, String> setProperty() { HashMap<String, String> pMap =
  • 每一个请求我都需要在请求头里面加上token这个请求头,作为一种校验机制,传统的接口可以通过设置一个全局的变量,然后通过页面携带过来(大概就是先将我们的token放在session中,写一个服务用来获取session中的...
  •  使用springMVC的时候,有些时候会需要获取请求或者响应对象,例如在身份验证的时候,需要获取请求头中的token,在做登录系统的时候需要使用response对象向客户端添加cookie,一个有效的做法是在controller的方法中...
  • Java安全验证之jwt(json web token)

    千次阅读 2017-08-10 17:25:50
    用户发起登录请求,服务端创建一个加密后jwt信息,作为token返回值,在后续请求jwt信息作为请求头,服务端正确解密后可获取到存储用户信息,表示验证通过;解密失败说明token无效或者已过期。jwt token的组成...
  • 注意:当指定其它名称时调用时则必须在请求header头中设置 service or X-service 属性,value为上一步重定向地址。 3.调用OAuth2.0password接口 java代码 <?xml version="1.0" encoding="U
  • * @return JSONObject(通过JSONObject.get(key)方式获取json对象属性值) */ public static JSONObject httpsRequest(String requestUrl, String requestMethod, String outputStr) { JSONObject jsonObject ...
  • 首先别人是写的网络接口归我们去通过http请求获取,然后我们在上传请求头时是依据后台写的验证条件决定我们需要不需要上传请求头,但是一般情况下:content-type(请求文件格式)是需要写在headers中的,另外就是...
  • // 把请求过来header请求头 原样设置到feign请求头中 if("Content-Type".equals(entry.getKey())){ continue; } requestTemplate.header(entry.getKey(), entry.getValue()); } } } private ...
  • 使用swagger测试,因为方法里要获取请求头中的token然后解析用户id出来,所以使用swagger会出问题 于是使用前端的页面,用浏览器查看,发现请求成功,但是返回数据为空 到后端控制台上查看,发现报Handler ...
  • // 从请求头中获取内容类型 String contentType = meidaConn.getHeaderField("Content-Type"); // 根据内容类型判断文件扩展名 String fileExt = WeixinUtil.getFileEndWitsh(contentType); // 请求体...
  • springboot整合JWT

    2020-05-28 19:52:34
    springboot整合JWT一、JWT介绍1.JWT格式2...将token放入请求头中请求 一、JWT介绍 JSON Web token简称JWT, 是用于对应用程序上用户进行身份验证标记。也就是说, 使用 JWTS 应用程序不再需要保存有关其用户 c
  • 2.HTTP Header Manager添加登录用户的token令牌,可以在接口抓包中获取token对应的请求头信息 3.添加定时器,并填写导出的变量名,此处定义为number 4.在http请求,引用number变量(注:我文件夹下的图片命名...
  • 不建议使用@autowired进行注入,建议使用CHERRY.SPRING_CONTEXT.getBean(xxx.class)获取Spring容器中的bean 建议系统接口以/api开头,给第三方暴露的接口,不需要认证的接口以/interface开头 建议所有业务代码均按照...
  • 刷新后新的AccessToken过期时间依旧为5分钟,时间戳为当前最新时间戳,同时也设置RefreshToken中的时间戳为当前最新时间戳,刷新过期时间重新为30分钟过期,最终将刷新的AccessToken存放在Response的Header中的...
  • 类别侧边栏的实现后,需要为每一个类别的元素都添加一个id,通过id来获取数据库中的数据,用Ajax获取数据并且刷新页面的信息。采用分页技术,防止数据过多的时候,显示在同一个页面,给用户带来不好的体验,分页支持...
  • 用 Swagger 测试接口,怎么在请求头中携带 Token? cors-1、cors-2 Spring Boot 中三种跨域场景总结 httpbasic Spring Boot 中如何实现 HTTP 认证? authorize Spring Security 中的四种权限控制方式 ...
  • 它是一个很易用与Java项目的的安全框架,提供了认证、授权、加密、会话管理,与spring Security 一样都是做一个权限安全框架,但是与Spring Security 相比,在于 Shiro 使用了比较简单易懂易于使用授权方式。...
  • 28.2.1请求头认证(Siteminder) 219 Siteminder示例配置 219 28.2.2 Java EE容器认证 220 29. LDAP认证 220 29.1概述 220 29.2在Spring Security使用LDAP 221 29.3配置LDAP服务器 221 29.3.1使用嵌入式测试服务器...
  • 第02节、Http请求头分析 第03节、使用时间戳解决浏览器缓存问题 第04节、Http反盗链技术概念 第05节、Http防盗链技术代码实现 第06节、重定向实现原理 资料+源码.rar 0017-蚂蚁课堂(每特学院)-2期-表单重复提交&...

空空如也

空空如也

1 2
收藏数 28
精华内容 11
关键字:

java获取请求头中的token

java 订阅