[spring security 那点事儿]配置方式

这段时间一直开发的B2C的网购平台已经完成了将近一半的功能,突然觉得自己之前对于权限管理方面的hold决定将给后面带来不小的工作量,所以决定现在就加入权限判断的功能。很容易联想到spring security来做这个事情,先看看一个官方文档的翻译版本:

http://www.family168.com/tutorial/springsecurity/html/springsecurity.html

写的有些简略,但是足以能step by step的执行下去。这里总结一下今天通过命名空间方式的配置过程吧。

既然要做到自动拦截并进行权限判断,很明显,对于spring security而言,需要有一个监听器,这个的配置很容易,类似于spring的监听容器一样,web.xml中加入配置

 

然后剩下的事情更简单了,通常而言,系统中部分url或者代码希望被拦截并检测权限,如这里应用到的后台管理系统,还有一部分是不需要进行拦截的,比如系统的首页。那么这个事情是需要你告诉spring security的,在2.0之后引入的namespace的方式将这个过程简化的非常容易,也就是使用<http/>的方式,这里暂且略过那段简单的代码,你可以在上面的文档第二章看到那个只有短短几行的配置,却实现了一个最初的demo。

这里说说遇到的问题,那就是关于auto-config的问题,auto-config设置为true,spring security默认加载了过滤器并且修正其过滤器的执行顺序,避免了由于过滤器执行顺序不合适导致的异常。但是这里一旦配置成默认的true方式,那么如果你要指定多个验证数据来源也就是provider,会出现异常:

SecurityConfigurationException: More than one UserDetailsService registered. Please use a specific Id in your configuration

这个异常出现的原因就是因为你使用了auto-config=true,同时又配置了多个UserDetailsService的bean,导致auto-config中默认加载的<remember-me>在装配UserDetailsService的时候找不到合适的bean,注意这里的装配是byType的。比如下面的代码就配置了两个provider,一个是通过数据库来获取数据,一个在内存中常驻一个默认的超级用户的配置:

上面的JdbcDaoImpl和InMemoryDaoImpl都是实现了接口UserDetailsService,分别制定了datasource和usermap作为用户数据的来源。

这个类似于你配置了两个相同名称的bean,却制定了autoWired=byName一样的道理。解决方法也很简单,你只需要去掉auto-config=true,然后手动填写需要的过滤器类型,如果你需要<remember-me/>那么就手动指定它的userDetailService,如下:

我希望来自数据库的用户的数据库可以被写入cookie从而实现页面上的诸如“2周内自动登录”的功能,因为内存的那些账户是预留的默认最高权限用户。当然可能应用场景不同于这样的简单,但是解决方案的原理也是相同的。

正如上面所示,我们制定了两个userDetailService,一个定位于数据库,一个定位于内存,所以同样的需要配置两个provider来告诉spring security这两个的数据提供者:

 

好了,工作已经完成了,剩下的你可能会想两方面的问题:

1、页面的权限验证是怎么执行的?

2、数据库的数据哪里来的?我能否自定义表结构来整合自己的项目特殊需求?

 

第一个问题,权限验证如何执行的?看看这里的http的配置:

很简单,指明了登录页面,默认登录成功的定位地址,注销后的定位地址,特别注意的是这里我们必须配置对于图片和css、js等资源的请求不能被拦截掉,否则页面会丢失样式,这里需要手动的设置对于资源文件的请求放行,即过滤器不执行拦截,同时由于我们系统使用了dwr来实现异步交互,所以同样的这里也是放行,如果需要进行权限判断,则通过其他方式如方法权限判断等实现。

 这里我们自定义了登录页面,而不是使用spring security那个没有任何样式的页面,那么在自己的登录页面的登录表单中,要怎么去整合spring security呢,很容易,只要将input的名字符合其要求即可:

要注意一下action的url。上面的从session中取出的,是权限校验失败的情况下的错误异常信息,这些信息由于使用的是namespace的方式,并不能像以前普通bean放下的配置显示具体的错误类型,但是这个也没什么关系,由于那个message.properties是一个英文文件,如果要将详细的信息显示出来,需要执行国际化,但是这里其实错误并无太紧急的需求显示详细,所以后续可以通过其他的机制,来显示一个通用性的信息即可,或者研究一下在这种namespace的方式下,如何去设置这个地方。

 

如果既配置http又配置了providerManager会怎样?http会有效,其中的NamespaceAuthenticationManager方法providerBeanNames参数保存了namespace方式的配置的默认的provider列表,如果这个参数为空,才回去获取配置的providerManager配置的provider,但是矛盾的是,如果providerBeanNames为空,却会抛出

No authentication providers were found in the application context异常!

所以,这也是行不通的。这里的应用场景较为初级的使用了spring security,下面要进行的,是针对于本系统的一些特性,尤其是后台的富客户端情况下,无法简单的通过url拦截的方式来实现权限控制的情况。

 

第二个问题,处理起来也很简单,看看官方文档,写的很清楚了,不罗嗦了

http://www.family168.com/tutorial/springsecurity/html/appendix-schema.html

 

 

 

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值