spirng-boot利用spring-security实现token权限系统
2018-03-21 15:07:26
1262 次阅读
0 个评论
用过spring-security的都应该能感觉到,spring-security把authentication和authorization封装的比较死。默认的authorization是基于session的。利用session验证过的信息,保存进SecurityContext,权限系统再根据SecurityContext保存的用户权限相关信息,来进行权限管理。 
但是在目前的场景中,服务器端往往要满足多端的验证方式,session的方式不容易和移动端配合的好。更多的是用一个token放在http header中进行验证。这种就需要绕开spring-security默认的authentication直接利用它的authorization。
在这里我演示一个在spring-security做方法级别拦截的方案。
我们再来看一下SecurityContext到底封装了什么。
但是在目前的场景中,服务器端往往要满足多端的验证方式,session的方式不容易和移动端配合的好。更多的是用一个token放在http header中进行验证。这种就需要绕开spring-security默认的authentication直接利用它的authorization。
在这里我演示一个在spring-security做方法级别拦截的方案。
这里就是基于token的spring-boot安全拦截配置
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
@Order(1)
public class TokenBasedSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) {
        try {
            http.addFilterBefore(... SecurityContextPersistenceFilter.class);
            http.securityContext().securityContextRepository(new SecurityContextRepository() {
                @Override
                public SecurityContext loadContext(HttpRequestResponseHolder requestResponseHolder) {
                    ...
                }
                @Override
                public void saveContext(SecurityContext context, HttpServletRequest request, HttpServletResponse response) {
                    ...
                }
                @Override
                public boolean containsContext(HttpServletRequest request) {
                    ...
                }
            });
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
} 在这里,我们要做的其实就是设置重在SecurityContextRepository。这个实体在spring security启动中要传递给SecurityContextPersistenceFilter。这个filter根据request来加载SecurityContext。而SecurityContextPersistenceFilter就是从其内部的SecurityContextRepository来加载SecurityContext的。所以我们就需要重载上面代码中的三个方法,根据request来构造SecurityContext。 我们再来看一下SecurityContext到底封装了什么。
public interface SecurityContext extends Serializable {
    Authentication getAuthentication();
    void setAuthentication(Authentication authentication);
} Authentication而已。 
public interface Authentication extends Principal, Serializable {
    Collection<? extends GrantedAuthority> getAuthorities();
    Object getCredentials();
    Object getDetails();
    Object getPrincipal();
    boolean isAuthenticated();
    void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}
在这里我们还要构造一个机遇token的Authentication接口的实现。在实现中对于权限来说很有用的就是getAuthorities方法。我们只要给其封装最简单的SimpleGrantedAuthority就好了。
  这样我们就可以给我们的Controller方法做拦截了
@RestController
@RequestMapping(value = "test")
public class TestController {
    @PreAuthorize("hasAuthority('super_admin')")
    @RequestMapping(value = "hello", method = RequestMethod.GET)
    public String superHello(@RequestParam String domain) {
        return new String("super hello");
    }
}
相关话题
- spring boot拦截器验证token防止表单重复提交
 - spring boot集成Hibernate配置
 - DelayQueue实现支付系统异步通知
 - 开放接口api的Token签名sign设计与实现
 - Spring Boot启动时执行指定方法
 - Spring+redis实现session集群
 - Spring Boot配置@ConditionalOnProperty来控制Configuration是否生效
 - jackson Spring boot 枚举类型不区分大小写映射
 - 解决Spring Boot+AngularJS因为跨域导致Session丢失问题
 - Spring boot打包后从类路径目录中获取资源列表
 - 最新商城系统推荐
 - Spring Boot指定某个Controller支持跨源请求,以及如何让Controller类某个成员方法支持跨源请求
 - 分布式文件系统选型
 - Fabric.js实作网格系统
 - 使用commons-vfs监听文件系统