spring security是spring boot里用来进行系统访问安全控制的框架,可以对登录的用户进行认证和授权。今天写这篇文章不是教大家如何配置和使用这个框架的,毕竟这玩意儿网上随便搜一下就一大堆教程,今天写这篇文章的目的是分享一下我在使用过程中遇到的一个问题。
问题主要发生了对登录用户进行授权的部分,代码是这样的:
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers("/product/**").hasRole("USER")
.antMatchers("/admin/**").hasRole("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin().and()
.httpBasic();
}
其中有两行是对需要访问的url进行授权的,product/路径只能是“USER”角色的用户访问,admin/路径只允许角色设定为“ADMIN”的用户访问。于是我在数据库的user表里插入了两条数据:
user | ... | role |
---|---|---|
user1 | ... | USER |
admin | ... | ADMIN |
但是奇迹发生了,无论我怎么登录,都提示我403,突然慌了,对照着教程写代码,最怕突然出现问题,而且还不知道什么问题。怎么办呢,先尝试着缩小问题范围,看一下是代码有问题还是数据有问题,我把
...
// .antMatchers("/product/**").hasRole("USER")
// .antMatchers("/admin/**").hasRole("ADMIN")
...
两行代码注释了重新运行,发现可以正常登录,那基本就说明用户名密码的认证没有问题,问题只能出现在role不匹配上,其实这时候我的猜测是我的代码没有正确地将role传给spring security,接下来依靠调试去确定为什么我传递role的代码没有生效。
经过一阵乱捣鼓,在调试模式下追踪堆栈终于找到了spring security进行role匹配的代码,结果让我大吃一惊,我的role的值确实已经正确传递给spring,但是spring里预期的role值竟然是“ROLE_USER”和"ROLE_ADMIN",纳尼!我和我的小伙伴都惊呆了,翻看了一下上下文的代码,原来spring security里有一段逻辑是取出的role都会带一个默认前缀,这个前缀就是:
defaultRolePrefix="ROLE_";
真相终于大白了。但是我好生气啊,这代码里也没有啥提示,非得给我加个前缀,那我要是偏偏不想加呢,于是我试图去找有没有解决方案可以忽略spring的默认前缀,试了网上所说的一两种方案,我更生气了,根本没效果,这些人回答问题真的有自己试过吗?
看样子要搞定spring不简单,想想spring本身也没啥毛病,那我还是选择搞定自己吧。把数据库的role值都带上“ROLE_”前缀之后果然就过了,肉牛满面。
这个问题我估计文档里应该是有的,也不是什么大问题,但要遇到了却不知道怎么回事还是挺不开心的,所以希望这篇文章能给后来者节省一点走弯路的时间。