springsecuity拦截匹配URL权限(RequestMatcher接口详解)

springsecuity拦截匹配URL权限(RequestMatcher接口详解)

2023年6月25日发(作者:)

springsecuity拦截匹配URL权限(RequestMatcher接⼝详解)我们知道spring secuity是控制URL的访问权限的,那么spring secuity是怎样拦截匹配URL,我们先看⼀个接⼝RequestMatcher匹配HttpServletRequest的简单策略接⼝RequestMatcher,其下定义了matches⽅法,如果返回是true表⽰提供的请求与提供的匹配规则匹配,如果返回的是false则不匹配。匹配HttpServletRequest的简单策略接⼝RequestMatcher其实现类:AntPathRequestMatcher:重点MvcRequestMatcher:重点RegexRequestMatcher: 根据正则模式进⾏匹配AnyRequestMatcherAntPathRequestMatcher其javadoc描述如下:Matcher which compares a pre-defined ant-style pattern against the URL (servletPath + pathInfo) of anHttpServletRequest. The query string of the URL is ignored and matching is case-insensitive or case-sensitivedepending on the arguments passed into the r将预先定义的ant风格与URL进⾏⽐较(⼀个HttpServletRequest的servletPath + pathInfo)。 查询字符串⽹址被忽略,匹配是否区分⼤⼩写具体取决于传递给构造函数的参数(详细可查看AntPathRequestMatcher的三个⼊参的构造函数)Using a pattern value of /** or ** is treated as a universal match, which will match any request. Patterns which end with/** (and have no other wildcards) are optimized by using a substring match — a pattern of /aaa/** will match /aaa,/aaa/ and any sub-directories, such as /aaa/bbb/ccc.使⽤/** 或 ** 的模式值被视为通⽤匹配,这将匹配任何请求。 以/** 结尾的模式(并且没有其他通配符)⽐如 /aaa/** 的模式将匹配/aaa,/aaa/和任何⼦⽬录,例如/aaa/bbb/ccc。所谓Apache Ant的样式路径,有三种通配符的匹配⽅式1. ? 匹配任意单个字符2.

1. 匹配0或者任意数量的字符3. ** 匹配0或者更多的⽬录做url匹配的时候,不需要加上context path,只匹配servletPath + pathInfo,关于context path,servletPath,pathInfo的讲解在第⼀节已经讲解过了,想了解详细可以去查看。⽰列定义依赖定义相关的依赖及jetty插件,设置了context path为/websecuity-quickstart-url01 secuity-quickstart-url01 framework spring-webmvc E ty spring-security-web E ty spring-security-config E t t-api 3.1.0 provided jsp-api 2.2 provided secuity-quickstart-url01 s maven-war-plugin 3.0.0 false jetty-maven-plugin 9.4.3.v20170317 8001 /web 定义系统启动类:定义了servletPath为/v1public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { //系统启动的时候的根类 @Override protected Class[] getRootConfigClasses() { return new Class[]{}; } @Override protected Class[] getServletConfigClasses() { return null; } @Override protected String[] getServletMappings() { return new String[]{"/v1/*"}; }}web⼊⼝类@EnableWebMvc@EnableWebSecurity@ComponentScan("y")public class WebAppConfig extends WebMvcConfigurerAdapter { public void configureDefaultServletHandling(DefaultServletHandlerConfigurer configurer) { (); }}spring security配置类public class WebAppSecurityInitializer extends AbstractSecurityWebApplicationInitializer { protected String getDispatcherWebApplicationContextSuffix() { return T_SERVLET_NAME; }}具体的Controller@RestControllerpublic class HelloController { @GetMapping("/hello") public String hello(){ return "hello spring secuity"; } @PostMapping("/world") public String world(){ return "world spring secuity"; } @GetMapping("/home") public String home(){ return "home spring secuity"; } @GetMapping("/admin") public String admin(){ return "admin spring secuity"; }}权限⽤户名密码的具体配置@Configurationpublic class WebSecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(AuthenticationManagerBuilder auth) throws Exception { ryAuthentication().withUser("zhangsan").password("123456").roles("GUEST"); ryAuthentication().withUser("").password("123456").roles("USER"); ryAuthentication().withUser("lisi").password("12345678").roles("USER", "ADMIN"); } protected void configure(HttpSecurity http) throws Exception { //post请求默认的都开启了csrf的模式,所有post请求都必须带有token之类的验证信息才可以进⼊登陆页⾯,这边是禁⽤csrf模式 ().disable(); //表⽰所有的get请求都不需要权限认证 //izeRequests().antMatchers().access("permitAll"); //对/hello 进⾏匹配,不管HTTP METHOD是什么 //izeRequests().antMatchers("/v1/hello").hasRole("USER"); //匹配/hello,且http method是POST,需要权限认证 //izeRequests().antMatchers(, "/v1/world").hasRole("USER"); //匹配 /hello,且http method是GET,不需要权限认证 //izeRequests().antMatchers(, "/v1/hello").access("permitAll"); //匹配/admin,并且http method不管是什么,需要admin权限 izeRequests().antMatchers("/v1/admin").hasRole("ADMIN"); izeRequests().antMatchers("/**/*.html").access("permitAll"); izeRequests().antMatchers("/**/*.css").access("permitAll"); izeRequests().antMatchers("/**/*.js").access("permitAll"); izeRequests().antMatchers("/**/*.png").access("permitAll"); izeRequests().anyRequest().authenticated(); gin(); }}验证发现虽然我们配置了context path,但是在权限配置中是不需要配置context path,servletPath需要配置localhost:8001/web/v1/adminlocalhost:8001/web/v1/hello参考资料MvcRequestMatcher其javadoc描述如下:A RequestMatcher that uses Spring MVC's HandlerMappingIntrospector to match the path and extract tMatcher使⽤Spring MVC的HandlerMappingIntrospector来匹配路径并提取变量。It is important to understand that Spring MVC's matching is relative to the servlet path. This means if you havemapped any servlet to a path that starts with "/" and is greater than one, you should also specify the#setServletPath(String) attribute to differentiate mappings.对我们⽽⾔了解Spring MVC的匹配是相对于servlet路径这⼀点是⾮常重要的。 这意味着如果您已经将任何servlet映射到以“/String”开头,则还应该指定#setServletPath(String)属性以区分相关映射匹配。MvcRequestMatcher是根据server_path来匹配的。⽰列配置类和上⾯都差不多,不⼀样的是下⾯的类,定义系统启动类:public class WebAppInitializer extends AbstractAnnotationConfigDispatcherServletInitializer { //系统启动的时候的根类 @Override protected Class[] getRootConfigClasses() { return new Class[]{}; } @Override protected Class[] getServletConfigClasses() { return null; } @Override protected String[] getServletMappings() { return new String[]{"/v1/*","/v2/*"}; }}权限⽤户名密码的具体配置@Configurationpublic class WebSecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(AuthenticationManagerBuilder auth) throws Exception { ryAuthentication().withUser("zhangsan").password("123456").roles("GUEST"); ryAuthentication().withUser("").password("123456").roles("USER"); ryAuthentication().withUser("lisi").password("12345678").roles("USER", "ADMIN"); } protected void configure(HttpSecurity http) throws Exception { ().disable(); //localhost:8001/web/v1/hello get⽅式 可以访问 //izeRequests().mvcMatchers(,"hello").access("permitAll"); //localhost:8001/web/v1/hello post⽅式,需要权限认证之后才能访问 //izeRequests().mvcMatchers(,"hello").hasRole("USER"); //我们配置了servletPath,多个servletPath的时候这种配置也能进⾏url访问的更加细粒度化, //localhost:8001/web/v1/hello不需要权限认证 //localhost:8001/web/v2/hello需要权限认证 izeRequests().mvcMatchers(,"hello").servletPath("/v1").access("permitAll"); izeRequests().mvcMatchers(,"hello").servletPath("/v2").access("hasRole('USER')"); izeRequests().antMatchers("/**/*.html").access("permitAll"); izeRequests().antMatchers("/**/*.css").access("permitAll"); izeRequests().antMatchers("/**/*.js").access("permitAll"); izeRequests().antMatchers("/**/*.png").access("permitAll"); izeRequests().anyRequest().authenticated(); gin(); }}总结servletPath配置的三种模式,第⼀种配置⽅式 servlet Path 为空第⼆种配置⽅式 servlet Path /aaa, /aaa/bbb/第三种配置⽅式servlet Path /.do, /.action这三种情况只有第⼆种需要去配置servletPath,其他⼆种都不需要。具体配置的时候⾃⼰去调试⼀下。MvcRequestMatcher和AntPathRequestMatcher的区别:如果配置了servlet_path,那么AntPathRequestMatcher在配置antMatchers的时候需要加上servlet_path,⽐如如果加了@Overrideprotected String[] getServletMappings() { return new String[]{"/v1/*","/v2/*"};}那么antMatchers("/v1/hello"),⽽mvcMatchers不需要加上servlet_path参考资料AnyRequestMatcher匹配所有的请求⽰列权限⽤户名密码的具体配置@Configurationpublic class WebSecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(AuthenticationManagerBuilder auth) throws Exception { ryAuthentication().withUser("zhangsan").password("123456").roles("GUEST"); ryAuthentication().withUser("").password("123456").roles("USER"); ryAuthentication().withUser("lisi").password("12345678").roles("USER", "ADMIN"); } protected void configure(HttpSecurity http) throws Exception { ().disable(); //匹配所有请求都不需要权限控制 //izeRequests().anyRequest().access("permitAll"); //匹配所有的请求都需要USER权限 izeRequests().anyRequest().hasRole("USER"); izeRequests().antMatchers("/**/*.html").access("permitAll"); izeRequests().antMatchers("/**/*.css").access("permitAll"); izeRequests().antMatchers("/**/*.js").access("permitAll"); izeRequests().antMatchers("/**/*.png").access("permitAll"); //我们平时写的authenticated,指的是上⾯配置没有匹配到的url都需要权限认证,但是不管是什么权限,不管是USER,GUEST,ADMIN都可以 izeRequests().anyRequest().authenticated(); gin(); }}验证localhost:8001/web/v1/hellolocalhost:8001/web/v1/homelocalhost:8001/web/v1/admin参考资料⾃定义RequestMatcher⽰列权限⽤户名密码的具体配置spring secuity提供了requestMatchers⼊⼝让我们⾃定义⾃⼰的RequestMatcher实现类@Configurationpublic class WebSecurityConfig extends WebSecurityConfigurerAdapter { protected void configure(AuthenticationManagerBuilder auth) throws Exception { ryAuthentication().withUser("zhangsan").password("123456").roles("GUEST"); ryAuthentication().withUser("").password("123456").roles("USER"); ryAuthentication().withUser("lisi").password("12345678").roles("USER", "ADMIN"); } protected void configure(HttpSecurity http) throws Exception { ().disable(); //spring secuity提供了requestMatchers接⼝,等价于izeRequests().anyRequest().access("permitAll"); //izeRequests().requestMatchers(CE).access("permitAll"); //参数中type等于1的就不做权限认证, // 当访问的url地址为localhost:8001/web/v1/hello?type=1,因为type值是1,所以匹配 izeRequests().requestMatchers((RequestMatcher) request -> "1".equals(ameter("type"))).access("permitAll"); izeRequests().antMatchers("/**/*.html").access("permitAll"); izeRequests().antMatchers("/**/*.css").access("permitAll"); izeRequests().antMatchers("/**/*.js").access("permitAll"); izeRequests().antMatchers("/**/*.png").access("permitAll"); izeRequests().anyRequest().authenticated(); gin(); }}参考资料总结1. 做url匹配的时候,不需要加上context_path2. 顺序很重要,适合的url先匹配到的先应⽤上了。3. 我们在做权限控制的时候都在我们⾃⼰定义的WebSecurityConfig的configure(HttpSecurity http)⽅法中去定义的,WebSecurityConfig继承WebSecurityConfigurerAdapter我们看看WebSecurityConfigurerAdapter类中的configure默认的实现是什么: protected void configure(HttpSecurity http) throws Exception { ("Using default configure(HttpSecurity). If subclassed this will potentially override subclass configure(HttpSecurity)."); http .authorizeRequests() .anyRequest().authenticated() .and() .formLogin().and() .httpBasic(); }我们看到了任何请求需要认证以表单的形式,以httpbasic的⽅式进⾏认证。参考资料

发布者:admin,转转请注明出处:http://www.yc00.com/xiaochengxu/1687677998a30802.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信