SprintBoot Security 数据库验证请求token是否有效

0、思路

        1、jwt生成的token是永久的,每次登陆的时候需要把token存数据库,所以需要拦截每次请求带过来的token是否在数据库里面。

        2、验证之前需要过滤掉哪些不需要校验的url地址,避免duird和swg等这样的地址也走数据验证权限了

1、定义权限验证功能类

package com.java.core.core.security;

import java.io.IOException;
import java.util.Date;
import java.util.List;

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

import com.java.core.com.utils.http.HttpUtils;
import com.java.core.com.utils.spring.SpringUtils;
import com.java.core.com.vo.HttpResult;
import com.java.core.com.vo.HttpStatus;
import com.java.core.entity.SysUserOnline;
import com.java.core.service.system.SysUserOnlineService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;
import org.springframework.util.AntPathMatcher;

/**
 * 登录认证检查过滤器
 */
public class JwtAuthenticationFilter extends BasicAuthenticationFilter {

    //忽略的请求地址
    private  List<String> antMatchers;
    //匹配字符
    private boolean matchesPathPattern(String path) {
        boolean result=false;
        AntPathMatcher apm = new AntPathMatcher();
        for (String pattern:this.antMatchers) {
            result = apm.match(pattern, path);
            if(result)break;
        }

        return result;
    }
	@Autowired
    public JwtAuthenticationFilter(AuthenticationManager authenticationManager, List<String> antMatchers) {
        super(authenticationManager);
        this.antMatchers=antMatchers;
    }

    @Override
    protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
        if(!matchesPathPattern(request.getRequestURI())){
            //需要校验权限的请求地址
            String token = request.getHeader(JwtTokenUtils.AUTHORITIES);
            SysUserOnline user = SpringUtils.getBean(SysUserOnlineService.class).selectOnlineById(token);
            //为空,或者超时
            if(user == null || ((new Date().getTime()-user.getStart_timestamp().getTime())/1000/60)>user.getExpire_time()){
                HttpUtils.write(response, HttpResult.error(HttpStatus.SC_PROXY_AUTHENTICATION_REQUIRED,"登录凭证已经失效"));
                return;
            }
        }
        // 获取token, 并检查登录状态
        SecurityUtils.checkAuthentication(request);
        chain.doFilter(request, response);
    }
}

2、config注册和配置

package com.java.core.web.config;

import com.java.core.core.security.*;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.HttpMethod;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.CorsConfigurationSource;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

//登录配置

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Resource
    private UserDetailsService userDetailsService;

    @Override
    public void configure(AuthenticationManagerBuilder auth) throws Exception {
        // 使用自定义登录身份认证组件
        auth.authenticationProvider(new JwtAuthenticationProvider(userDetailsService));
    }

    //配置跨域
    private CorsConfigurationSource CorsConfigurationSource() {
        CorsConfigurationSource source = new UrlBasedCorsConfigurationSource();
        CorsConfiguration corsConfiguration = new CorsConfiguration();
        corsConfiguration.addAllowedOrigin("*");    //同源配置,*表示任何请求都视为同源,若需指定ip和端口可以改为如“localhost:8080”,多个以“,”分隔;
        corsConfiguration.addAllowedHeader("*");//header,允许哪些header,本案中使用的是token,此处可将*替换为token;
        corsConfiguration.addAllowedMethod("*");    //允许的请求方法,PSOT、GET等
        ((UrlBasedCorsConfigurationSource) source).registerCorsConfiguration("/**", corsConfiguration); //配置允许跨域访问的url
        return source;
    }
    //不做验证的地址
    private List<String> getAntMatchers(){
        List<String> list =  new ArrayList<String>();
        // 登录URL
        list.add("/login");
        //放行静态资源
        list.add("/**/*.css");
        list.add( "/**/*.js");
        list.add("/imgs/**");
        list.add("/favicon.ico");
        list.add("/static/**");
        //druid
        list.add("/druid/**");
        // Knife4j
        list.add("/swagger**/**");
        list.add("/webjars/**");
        list.add("/v2/**");
        list.add("/doc.html");
        list.add("/v2/api-docs-ext/**");
        return  list;
    }

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        // 禁用 csrf, 由于使用的是JWT,我们这里不需要csrf
        http.cors().configurationSource(CorsConfigurationSource()).and().csrf().disable()
                .authorizeRequests()
                // 跨域预检请求
                .antMatchers(HttpMethod.OPTIONS, "/**").permitAll();
        //不需要权限的页面
        for (String pre: getAntMatchers()) {
            http.authorizeRequests().antMatchers(pre).permitAll();
        }
        // 其他所有请求需要身份认证
        http.authorizeRequests().anyRequest().authenticated();
        // 1、登录、生成Token
        http.addFilterBefore(new JwtLoginFilter(authenticationManager()), UsernamePasswordAuthenticationFilter.class);
        // 2、验证Token
        http.addFilterBefore(new JwtAuthenticationFilter(authenticationManager(),getAntMatchers()), UsernamePasswordAuthenticationFilter.class);
        // 3、自定义登录和权限异常提示
        http.exceptionHandling().accessDeniedHandler(new JwtAuthenticationAccessDenied()).authenticationEntryPoint(new JwtAuthenticationEntryPoint());
        // 4、退出
        http.logout().logoutSuccessHandler(new JwtLogoutSuccessHandler());
    }
    @Bean
    @Override
    public AuthenticationManager authenticationManager() throws Exception {
        return super.authenticationManager();
    }

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值