spring security免登录动态配置方案2

news/2025/2/22 20:49:31

为什么80%的码农都做不了架构师?>>>   hot3.png

之前有篇文章讲了怎么进行免登录动态配置的方案,动用了反射去实现,有点黑魔法的味道,这里再介绍另外一种方案

permitAll

spring-security-config-4.2.3.RELEASE-sources.jar!/org/springframework/security/config/annotation/web/configurers/ExpressionUrlAuthorizationConfigurer.java

public final class ExpressionUrlAuthorizationConfigurer<H extends HttpSecurityBuilder<H>>
		extends
		AbstractInterceptUrlConfigurer<ExpressionUrlAuthorizationConfigurer<H>, H> {
	static final String permitAll = "permitAll";
	private static final String denyAll = "denyAll";
	private static final String anonymous = "anonymous";
	private static final String authenticated = "authenticated";
	private static final String fullyAuthenticated = "fullyAuthenticated";
	private static final String rememberMe = "rememberMe";

	private final ExpressionInterceptUrlRegistry REGISTRY;

    //......
        /**
		 * Specify that URLs are allowed by anyone.
		 *
		 * @return the {@link ExpressionUrlAuthorizationConfigurer} for further
		 * customization
		 */
		public ExpressionInterceptUrlRegistry permitAll() {
			return access(permitAll);
		}

        public ExpressionInterceptUrlRegistry access(String attribute) {
			if (not) {
				attribute = "!" + attribute;
			}
			interceptUrl(requestMatchers, SecurityConfig.createList(attribute));
			return ExpressionUrlAuthorizationConfigurer.this.REGISTRY;
		}

        private void interceptUrl(Iterable<? extends RequestMatcher> requestMatchers,
			Collection<ConfigAttribute> configAttributes) {
		for (RequestMatcher requestMatcher : requestMatchers) {
			REGISTRY.addMapping(new AbstractConfigAttributeRequestMatcherRegistry.UrlMapping(
					requestMatcher, configAttributes));
		}
	}
}

permitAll操作将“permitAll”这个attribute以及对应的requestMatchers添加到REGISTRY

思路

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http
                .authorizeRequests()
                .antMatchers("/css/**", "/js/**","/fonts/**").permitAll()
                .anyRequest().authenticated();
    }
}

这里重点注意这个anyRequest().authenticated(),可以看到没有配置permitAll的请求,都要求authenticated这个级别的,而AnonymousAuthenticationFilter设置的匿名级别只是anonymous。

于是我们的思路就来了,新建一个filter,插入在AnonymousAuthenticationFilter之前,对于免登录的设置为authenticated

DemoFilter

public class DemoFilter extends GenericFilterBean {

    private Object principal = "annoUser";

    private List<GrantedAuthority> authorities = AuthorityUtils.createAuthorityList("ROLE_ANNO");

    @Override
    public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException {
        private final Map<String,HttpMethod[]> annoPatternMap = new HashMap<String,HttpMethod[]>(){{
        //for demo, you can change it and read from db or else
        put("/index/demo",new HttpMethod[]{HttpMethod.GET});
    }};
    
        String uri = ((HttpServletRequest) servletRequest).getRequestURI();
        if(annoPatternMap.containsKey(uri)){
            if(SecurityContextHolder.getContext().getAuthentication() == null){
                SecurityContextHolder.getContext().setAuthentication(
                        createAuthentication((HttpServletRequest) servletRequest));
            }
        }else{
            Authentication auth = SecurityContextHolder.getContext().getAuthentication();
            System.out.println(auth == null);
            if(auth != null && auth instanceof UsernamePasswordAuthenticationToken){
                if(principal.toString().equals(auth.getPrincipal().toString())){
                    SecurityContextHolder.getContext().setAuthentication(null);
                }
            }
        }
        filterChain.doFilter(servletRequest, servletResponse);
    }
    
    protected Authentication createAuthentication(HttpServletRequest request) {
        UsernamePasswordAuthenticationToken auth = new UsernamePasswordAuthenticationToken(
                principal, "N/A", authorities);
        auth.setDetails(authenticationDetailsSource.buildDetails(request));

        return auth;
    }
}

这里创建了一个伪造的UsernamePasswordAuthenticationToken

这里有一点要注意一下,就在判断不是配置的允许匿名访问的url的时候,如果之前的token是我们设置的,则需要重新清空,防止一旦访问匿名url之后获取session再去越权访问其他没有配置的url。

配置filter

@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .addFilterBefore(new DemoFilter(),AnonymousAuthenticationFilter.class)
                .authorizeRequests()
                .antMatchers("/css/**", "/js/**","/fonts/**").permitAll()
                .anyRequest().authenticated();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth
                .inMemoryAuthentication()
                .withUser("admin").password("admin").roles("USER");
    }
}

在AnonymousAuthenticationFilter之前提前设置好SecurityContextHolder里头的authentication。

小结

这样基本就大功告成了,不过有几点需要注意:

  • 自定义的filter,可能存在执行两遍的问题,这点后面的文章来讲
  • 获取到的uri无法处理pathvariable的情况,需要根据url pattern来处理,这点后面再讲述一下

doc

  • spring security运行时配置ignore url

转载于:https://my.oschina.net/go4it/blog/1580044


http://www.niftyadmin.cn/n/710345.html

相关文章

有限元计算 求解笔记(上)

octave 基本操作 算数运算的符号&#xff1a;,-,*,/,^,() 注释用%标出&#xff0c;行内行间注释方法相同。 普通的函数: sin, cos,tan,asin, acos,atan,exp,log,sqrt,abs 矩阵&#xff1a;[ ] 【行间用&#xff1b;隔开】 矩阵计算使用的符号&#xff1a;,-,*,,’ 有限元…

mbr分区的单独磁盘的备份恢复

1.远程备份恢复以centos6为例 先备份为mbr文件 拷贝到centos7 主机中&#xff08;172.18.254.154&#xff09;[rootcentos6 ~]#dd if/dev/sda ofmbr bs1 count512[rootcentos6 ~]#scp mbr 172.18.254.154:/app/* scp 远程主机与当前主机互传文件命令格式&#xff1a;scp local_…

LR中select next row和update value on的设置

LR的参数的取值&#xff0c;和select next row和update value on的设置都有密不可分的关系。下表给出了select next row和update value on不同的设置&#xff0c;对于LR的参数取值的结果将不同&#xff0c;给出了详细的描述。 Select next row Update Value on 实际运行结果 …

Hive日志

日志记录了程序运行的过程&#xff0c;是一种查找问题的利器。Hive中的日志分为两种1. 系统日志&#xff0c;记录了hive的运行情况&#xff0c;错误状况。2. Job 日志&#xff0c;记录了Hive 中job的执行的历史过程。系统日志存储在什么地方呢 &#xff1f;在hive/conf/ hive-l…

Odoo进销存(采购、销售、仓库)入门教程 - 下

转帖地址&#xff1a;http://blog.csdn.net/wangnan537/article/details/46475105 2. 进销存实务 2.1 销售产品 李逍遥接到客户苏州美尚邻里超市购买10只乐扣乐扣拉杆箱的请求后&#xff0c;登录系统&#xff0c;点击菜单 [销售->销售->报价单]&#xff0c;点击新建&…

有限元计算 求解笔记(中)

有限元计算原理 4. 桁架结构 4.1 2D问题中的结构分析 有必要声明一下已经定义的值&#xff1a;全局坐标&#xff08;X,Y&#xff09;; local坐标&#xff08;x,y&#xff09;;全局坐标下的力和位移。 一个二力杆只能受沿杆方向的力。 在local坐标下&#xff1a; 4.1.1 坐…

asp.net MVC2 初探二

这一节我们看如何发布Asp.net MVC在项目的引用中设置上面三个dll的copy local为true&#xff0c;然后在项目上点击右键publish&#xff0c;publish到一个目录下。这个和一般的wenForm页面一样。然后进行网站配置确保这块是4.0&#xff0c;当然根据你装的.net版本&#xff0c;点…

有限元计算 求解笔记(下)

有限元计算原理 5. 实例问题 5.1 E是&#xff08;X&#xff0c;Y&#xff09;的函数 首先假设杨氏模量为常量E0&#xff0c;积分计算就是乘法&#xff1a; so 应变矩阵由节点坐标确定 单元刚度矩阵给出&#xff1a; 那么对于E为变量的情况&#xff0c;假设E的方程为 so…