首页 > 编程语言 > 详细

前后端分离的Web应用程序中使用Spring Security+Mybatis+JWT非对称加密+动态权限管理(三):跨域配置、安全配置

时间:2021-05-26 14:41:38      阅读:27      评论:0      收藏:0      [点我收藏+]

1、跨域配置是指允许跨域请求,前后端分离情况下,都会涉及跨域请求,因此要正确配置服务器的跨域设置,同时要与前端协调,使参数协一致才可以实现访问,全局配置如下:

package com.security;
import org.springframework.web.servlet.config.annotation.CorsRegistry;
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
public class WebMvcConfig implements WebMvcConfigurer{
    @Override
    public void addCorsMappings(CorsRegistry registry) {
        registry.addMapping("/**")
                .allowedOrigins("http://localhost:8081")
                .allowedMethods("GET", "HEAD", "POST", "PUT", "DELETE","OPTIONS")
                .allowedHeaders("Origin", "X-Requested-With", "Content-Type", "token", "Accept","Access-Control-Request-Method", "Access-Control-Request-Headers")
                .exposedHeaders("Access-Control-Allow-Origin", "Access-Control-Allow-Credentials")
                .allowCredentials(true)
                .maxAge(3600);
    }
}

allowedOrigins是指允许的来源,填写的内容要与前端发送请求一致;allowedMethods指请求方法,options一定要写上,因为get、post等请求之前都会预先做一次options请求;allowedHeaders是指请求头里可以含有信息;exposedHeaders是指返回的响应头部信息含有信息;allowCredentials为true时允许匿名访问;maxAge准备响应前的缓存持续的最大时间(以秒为单位)。

2、Spring Security配置文件,这是spring security的核心,配置代码如下。配置文件中@Autowired 七个对象,这在后续再详述。接下来引入两个Bean,其中一个是用于登录验证,是一个自定义过滤器,后续再详述。另一个用于提供密码加密方法,Bcrypt是一个自带盐的方法,建议用该方法加密。

技术分享图片
package com.security;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.config.annotation.web.configurers.UrlAuthorizationConfigurer;
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.access.intercept.FilterSecurityInterceptor;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;

import com.handler.AjaxAccessDeniedHandler;
import com.handler.AjaxAuthenticationEntryPoint;
import com.handler.AjaxAuthenticationSuccessHandler;
import com.handler.AjaxLogoutSuccessHandler;
import com.service.MyUserDetailsService;

@Configuration
public class MySecurityConfig extends WebSecurityConfigurerAdapter{
    @Autowired 
    private MyUserDetailsService myUserDetailsService;
    @Autowired
    private AjaxAuthenticationEntryPoint authenticationEntryPoint;
    @Autowired
    private JwtAuthenticationTokenFilter jwtAuthenticationTokenFilter;
    @Autowired
    private AjaxLogoutSuccessHandler logoutSuccessHandler;
    @Autowired
    private AjaxAccessDeniedHandler accessDeniedHandler;
    @Autowired
    private AjaxAuthenticationSuccessHandler authenticationSuccessHandler;
    @Autowired
    private CustomSecurityMetadataSource customSecurityMetadataSource;
    
    //身份验证的Filter
    @Bean
    LoginFilter loginFilter() throws Exception{
        LoginFilter loginFilter=new LoginFilter();
        loginFilter.setAuthenticationManager(authenticationManagerBean());
        loginFilter.setAuthenticationSuccessHandler(authenticationSuccessHandler);
        return loginFilter;
    }
    
    //选择加密方法Bcrypt方法
    @Bean
    PasswordEncoder passwordEncoder() {
        return new BCryptPasswordEncoder();
    }
    
    
    @Override
    protected void configure(HttpSecurity http) throws Exception {        
        ApplicationContext applicationContext=http.getSharedObject(ApplicationContext.class);
        
        //动态权限资源配置,customSecurityMetadataSource作为配置来源
        http.apply(new UrlAuthorizationConfigurer<>(applicationContext))
        .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
            @Override
            public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                object.setSecurityMetadataSource(customSecurityMetadataSource);
                //object.setRejectPublicInvocations(true); //所要请求路径都要在资源里配置才可访问(包括匿名访问)
                return object;
            }                      
        });
                    
        //无状态登录,取消session
        http.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS)
            .and()
            .httpBasic().authenticationEntryPoint(authenticationEntryPoint) //未登录处理
            .and()
            .authorizeRequests()
            .antMatchers("/login2").permitAll()
            //.anyRequest()
            //使用rbac 角色静态方式绑定资源
            //.access("@rbacauthorityservice.hasPermission(request,authentication)")
            //.and()
            //使用表单登录
            //.formLogin().successHandler(authenticationSuccessHandler).failureHandler(authenticationFailureHandler).permitAll()
            .and()
            .logout().logoutSuccessHandler(logoutSuccessHandler).permitAll()
            .and()
            .csrf().disable();
        
        //勾选“记住我”时
        http.rememberMe().rememberMeParameter("remember-me")
            .userDetailsService(myUserDetailsService).tokenValiditySeconds(300);
        
        //身份验证异常处理
        http.exceptionHandling().accessDeniedHandler(accessDeniedHandler);
        
        //请求资源时,如果带了token令牌,则使用jwt的Authentication进行认证
        http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
        
        // 禁用headers缓存
        http.headers().cacheControl();
    }
}
View Code

configure方法是spring security配置的核心。下面这段代码是配置动态权限的关键,其中的customSecurityMetadataSource是一个自定义类,后续将给出代码。object.setRejectPublicInvocations(true);这句的意思是在数据库的menu表里存在的路径才可以访问,这句不能写,因为我们的登录路径/login2需要允许匿名访问,否则任何人都无法访问了。

        http.apply(new UrlAuthorizationConfigurer<>(applicationContext))
        .withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {
            @Override
            public <O extends FilterSecurityInterceptor> O postProcess(O object) {
                object.setSecurityMetadataSource(customSecurityMetadataSource);
                //object.setRejectPublicInvocations(true); //所要请求路径都要在资源里配置才可访问(包括匿名访问)
                return object;
            }                      
        });

对于已完成登录认证的用户,在请求资源时,不需要二次认证,因此在提交验证之前经过一个自定义Filter,在这个Filter里验证token是否合法,如果合法就可直接通过验证,如果不合法,则进入身份认证。jwtAuthenticationTokenFilter就是自定义的Filter,后续再给出代码。

http.addFilterBefore(jwtAuthenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);

 

前后端分离的Web应用程序中使用Spring Security+Mybatis+JWT非对称加密+动态权限管理(三):跨域配置、安全配置

原文:https://www.cnblogs.com/wwwzgy/p/14812717.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!