用過spring-security的都應該能感受到,spring-security把authentication和authorization封裝的比較死。默認的authorization是基於session的。利用session驗證過的信息,保存進SecurityContext,權限系統再根據SecurityContext保存的用戶權限相關信息,來進行權限管理。spring
可是在目前的場景中,服務器端每每要知足多端的驗證方式,session的方式不容易和移動端配合的好。更多的是用一個token放在http header中進行驗證。這種就須要繞開spring-security默認的authentication直接利用它的authorization。安全
在這裏我演示一個在spring-security作方法級別攔截的方案。服務器
這裏就是基於token的spring-boot安全攔截配置session
@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
。app
咱們再來看一下SecurityContext
到底封裝了什麼。dom
public interface SecurityContext extends Serializable { Authentication getAuthentication(); void setAuthentication(Authentication authentication); }
Authentication而已。ide
public interface Authentication extends Principal, Serializable {spring-boot
Collection<? extends GrantedAuthority> getAuthorities(); Object getCredentials(); Object getDetails(); Object getPrincipal(); boolean isAuthenticated();
void setAuthenticated(boolean isAuthenticated) throws IllegalArgumentException;
}code
在這裏咱們還要構造一個機遇token的Authentication接口的實現。在實現中對於權限來講頗有用的就是getAuthorities
方法。咱們只要給其封裝最簡單的SimpleGrantedAuthority
就行了。token
這樣咱們就能夠給咱們的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"); } }