spirng-boot中,基於既有的token驗證方式,利用spring-security實現許可權系統

chenatu發表於2016-12-09

spirng-boot中,基於既有的token驗證方式,利用spring-security實現許可權系統

用過spring-security的都應該能感覺到,spring-security把authentication和authorization封裝的比較死。預設的authorization是基於session的。利用session驗證過的資訊,儲存進SecurityContext,許可權系統再根據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");
    }
}

文章原載於http://mrchenatu.com/2016/12/…

相關文章