转载自:https://www.nbucedog.com/blog/article/8
当Spring security认证成功了之后会返回一个authentication,里面包含一些用户的认证信息。但有时候里面已有的信息并不能满足我们的需求,比如说当我们使用org.springframework.security.core.userdetails.User这个类的时候
会得到下面这样的authentication
{ "authorities": [ { "authority": "add_admin" } ], "details": { "remoteAddress": "0:0:0:0:0:0:0:1", "sessionId": null }, "authenticated": true, "principal": { "password": null, "username": "nbucedog", "authorities": [ { "authority": "add_admin" } ], "accountNonExpired": true, "accountNonLocked": true, "credentialsNonExpired": true, "enabled": true }, "credentials": null, "name": "nbucedog" }可以看到这里关于用户的信息只有一个username,但其实我还想要用户的id,因为使用Spring注解进行权限认证时id会比username更保险(这个我后面会说)。
接下来我们看看怎么能够在authentication.principal里加入id吧
因为org.springframework.security.core.userdetails.User本身就是UserDetails的实现类,而且它里面有许多东西我们还要用,所以我们就直接继承它并加入自己的东西,这里加入一个id属性
这样之后,我们会得到一个authentication.principal里包含id的authentication
{ "authorities": [ { "authority": "add_admin" } ], "details": { "remoteAddress": "0:0:0:0:0:0:0:1", "sessionId": null }, "authenticated": true, "principal": { "password": null, "username": "nbucedog", "authorities": [ { "authority": "add_admin" } ], "accountNonExpired": true, "accountNonLocked": true, "credentialsNonExpired": true, "enabled": true, "id": 1 }, "credentials": null, "name": "nbucedog" }接下来我们就可以使用Spring注解进行权限配置了,比如要求只有用户自己能修改自己的用户信息
@RequestMapping(value = "/user",method = RequestMethod.PUT) @ResponseBody @PreAuthorize("#user.id==authentication.principal.id") public Map UpdateUser(@RequestBody User user){ try { User oldUser = userService.findById(user.getId()); oldUser.setNickname(user.getNickname()); oldUser.setSex(user.getSex()); oldUser.setPhone(user.getPhone()); oldUser.setMail(user.getMail()); oldUser.setResume(user.getResume()); userService.save(oldUser); return ResultTools.result(0); }catch (Exception e){ e.printStackTrace(); return ResultTools.dataResult(1000,e.getMessage()); } }接下来说说在代码里我们为什么使用了authentication.principal.id,而非authentication.principal.username 这里举个例子,假如我们使用了@PreAuthorize("#user.username==authentication.principal.username"),而某个用户名为badguys,id为2的bad guys提交了如下的json数据
{ "id":1, "username":"badguys", "nickname":"bad guys" ... }当id为2的bad guys用他自己注册的账户登录后,通过这个数据成功的通过了@PreAuthorize里的过滤条件,并且成功修改了id为1的用户信息。而当我们使用@PreAuthorize("#user.id==authentication.principal.id")时,这条带有攻击性的json数据则会被拦截。
