Signed-off-by: Eric Zhao <sczyh16@gmail.com>master
@@ -21,14 +21,27 @@ import java.lang.annotation.Retention; | |||||
import java.lang.annotation.RetentionPolicy; | import java.lang.annotation.RetentionPolicy; | ||||
import java.lang.annotation.Target; | import java.lang.annotation.Target; | ||||
/** | |||||
* @author lkxiaolou | |||||
* @since 1.7.1 | |||||
*/ | |||||
@Retention(RetentionPolicy.RUNTIME) | @Retention(RetentionPolicy.RUNTIME) | ||||
@Documented | @Documented | ||||
@Target({ElementType.METHOD}) | @Target({ElementType.METHOD}) | ||||
public @interface AuthAction { | public @interface AuthAction { | ||||
/** | |||||
* @return the privilege type | |||||
*/ | |||||
AuthService.PrivilegeType value(); | AuthService.PrivilegeType value(); | ||||
/** | |||||
* @return the target name to control | |||||
*/ | |||||
String targetName() default "app"; | String targetName() default "app"; | ||||
String message() default "No privilege"; | |||||
/** | |||||
* @return the message when permission is denied | |||||
*/ | |||||
String message() default "Permission denied"; | |||||
} | } |
@@ -27,8 +27,14 @@ import javax.servlet.http.HttpServletResponse; | |||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.lang.reflect.Method; | import java.lang.reflect.Method; | ||||
/** | |||||
* The web interceptor for privilege-based authorization. | |||||
* | |||||
* @author lkxiaolou | |||||
* @since 1.7.1 | |||||
*/ | |||||
@Component | @Component | ||||
public class AuthInterceptor implements HandlerInterceptor { | |||||
public class AuthorizationInterceptor implements HandlerInterceptor { | |||||
@Autowired | @Autowired | ||||
private AuthService<HttpServletRequest> authService; | private AuthService<HttpServletRequest> authService; |
@@ -13,9 +13,8 @@ | |||||
* See the License for the specific language governing permissions and | * See the License for the specific language governing permissions and | ||||
* limitations under the License. | * limitations under the License. | ||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.dashboard.filter; | |||||
package com.alibaba.csp.sentinel.dashboard.auth; | |||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthService; | |||||
import org.apache.commons.lang.StringUtils; | import org.apache.commons.lang.StringUtils; | ||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
import org.springframework.beans.factory.annotation.Value; | import org.springframework.beans.factory.annotation.Value; | ||||
@@ -30,39 +29,46 @@ import javax.servlet.ServletRequest; | |||||
import javax.servlet.ServletResponse; | import javax.servlet.ServletResponse; | ||||
import javax.servlet.http.HttpServletRequest; | import javax.servlet.http.HttpServletRequest; | ||||
import javax.servlet.http.HttpServletResponse; | import javax.servlet.http.HttpServletResponse; | ||||
import java.io.IOException; | import java.io.IOException; | ||||
import java.util.List; | import java.util.List; | ||||
/** | /** | ||||
* Servlet Filter that authenticate requests. | |||||
* | |||||
* Note: | |||||
* Some urls are excluded as they needn't auth, such as: | |||||
* <p>The Servlet filter for authentication.</p> | |||||
* | * | ||||
* Index url: / | |||||
* Authentication request url: /login,logout | |||||
* Used for client: /registry/machine | |||||
* Static resources: htm,html,js and so on. | |||||
* <p>Note: some urls are excluded as they needn't auth, such as:</p> | |||||
* <ul> | |||||
* <li>index url: {@code /}</li> | |||||
* <li>authentication request url: {@code /login}, {@code /logout}</li> | |||||
* <li>machine registry: {@code /registry/machine}</li> | |||||
* <li>static resources</li> | |||||
* </ul> | |||||
* | * | ||||
* The excluded urls and urlSuffixes are configured in application.properties | |||||
* The excluded urls and urlSuffixes could be configured in {@code application.properties} file. | |||||
* | * | ||||
* @author cdfive | * @author cdfive | ||||
* @since 1.6.0 | * @since 1.6.0 | ||||
*/ | */ | ||||
@Component | @Component | ||||
public class AuthFilter implements Filter { | |||||
public class LoginAuthenticationFilter implements Filter { | |||||
private static final String URL_SUFFIX_DOT = "."; | private static final String URL_SUFFIX_DOT = "."; | ||||
/**Some urls which needn't auth, such as /auth/login,/registry/machine and so on*/ | |||||
/** | |||||
* Some urls which needn't auth, such as /auth/login, /registry/machine and so on. | |||||
*/ | |||||
@Value("#{'${auth.filter.exclude-urls}'.split(',')}") | @Value("#{'${auth.filter.exclude-urls}'.split(',')}") | ||||
private List<String> authFilterExcludeUrls; | private List<String> authFilterExcludeUrls; | ||||
/**Some urls with suffixes which needn't auth, such as htm,html,js and so on*/ | |||||
/** | |||||
* Some urls with suffixes which needn't auth, such as htm, html, js and so on. | |||||
*/ | |||||
@Value("#{'${auth.filter.exclude-url-suffixes}'.split(',')}") | @Value("#{'${auth.filter.exclude-url-suffixes}'.split(',')}") | ||||
private List<String> authFilterExcludeUrlSuffixes; | private List<String> authFilterExcludeUrlSuffixes; | ||||
/**Authentication using AuthService interface*/ | |||||
/** | |||||
* Authentication using AuthService interface. | |||||
*/ | |||||
@Autowired | @Autowired | ||||
private AuthService<HttpServletRequest> authService; | private AuthService<HttpServletRequest> authService; | ||||
@@ -72,7 +78,8 @@ public class AuthFilter implements Filter { | |||||
} | } | ||||
@Override | @Override | ||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { | |||||
public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) | |||||
throws IOException, ServletException { | |||||
HttpServletRequest httpRequest = (HttpServletRequest) request; | HttpServletRequest httpRequest = (HttpServletRequest) request; | ||||
String servletPath = httpRequest.getServletPath(); | String servletPath = httpRequest.getServletPath(); |
@@ -16,8 +16,11 @@ | |||||
package com.alibaba.csp.sentinel.dashboard.config; | package com.alibaba.csp.sentinel.dashboard.config; | ||||
import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; | import com.alibaba.csp.sentinel.adapter.servlet.CommonFilter; | ||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthInterceptor; | |||||
import com.alibaba.csp.sentinel.dashboard.filter.AuthFilter; | |||||
import com.alibaba.csp.sentinel.adapter.servlet.callback.WebCallbackManager; | |||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthorizationInterceptor; | |||||
import com.alibaba.csp.sentinel.dashboard.auth.LoginAuthenticationFilter; | |||||
import com.alibaba.csp.sentinel.util.StringUtil; | |||||
import org.slf4j.Logger; | import org.slf4j.Logger; | ||||
import org.slf4j.LoggerFactory; | import org.slf4j.LoggerFactory; | ||||
import org.springframework.beans.factory.annotation.Autowired; | import org.springframework.beans.factory.annotation.Autowired; | ||||
@@ -29,6 +32,7 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry | |||||
import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; | import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; | ||||
import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; | ||||
import javax.annotation.PostConstruct; | |||||
import javax.servlet.Filter; | import javax.servlet.Filter; | ||||
/** | /** | ||||
@@ -40,14 +44,14 @@ public class WebConfig implements WebMvcConfigurer { | |||||
private final Logger logger = LoggerFactory.getLogger(WebConfig.class); | private final Logger logger = LoggerFactory.getLogger(WebConfig.class); | ||||
@Autowired | @Autowired | ||||
private AuthFilter authFilter; | |||||
private LoginAuthenticationFilter loginAuthenticationFilter; | |||||
@Autowired | @Autowired | ||||
private AuthInterceptor authInterceptor; | |||||
private AuthorizationInterceptor authorizationInterceptor; | |||||
@Override | @Override | ||||
public void addInterceptors(InterceptorRegistry registry) { | public void addInterceptors(InterceptorRegistry registry) { | ||||
registry.addInterceptor(authInterceptor).addPathPatterns("/**"); | |||||
registry.addInterceptor(authorizationInterceptor).addPathPatterns("/**"); | |||||
} | } | ||||
@Override | @Override | ||||
@@ -77,10 +81,24 @@ public class WebConfig implements WebMvcConfigurer { | |||||
return registration; | return registration; | ||||
} | } | ||||
@PostConstruct | |||||
public void doInit() { | |||||
// Example: register a UrlCleaner to exclude URLs of common static resources. | |||||
WebCallbackManager.setUrlCleaner(url -> { | |||||
if (StringUtil.isEmpty(url)) { | |||||
return url; | |||||
} | |||||
if (url.endsWith(".js") || url.endsWith(".css") || url.endsWith("html")) { | |||||
return null; | |||||
} | |||||
return url; | |||||
}); | |||||
} | |||||
@Bean | @Bean | ||||
public FilterRegistrationBean authenticationFilterRegistration() { | public FilterRegistrationBean authenticationFilterRegistration() { | ||||
FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>(); | FilterRegistrationBean<Filter> registration = new FilterRegistrationBean<>(); | ||||
registration.setFilter(authFilter); | |||||
registration.setFilter(loginAuthenticationFilter); | |||||
registration.addUrlPatterns("/*"); | registration.addUrlPatterns("/*"); | ||||
registration.setName("authenticationFilter"); | registration.setName("authenticationFilter"); | ||||
registration.setOrder(0); | registration.setOrder(0); | ||||
@@ -15,7 +15,7 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.dashboard.controller.gateway; | package com.alibaba.csp.sentinel.dashboard.controller.gateway; | ||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthInterceptor; | |||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthorizationInterceptor; | |||||
import com.alibaba.csp.sentinel.dashboard.auth.FakeAuthServiceImpl; | import com.alibaba.csp.sentinel.dashboard.auth.FakeAuthServiceImpl; | ||||
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | ||||
import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity; | import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.ApiDefinitionEntity; | ||||
@@ -61,7 +61,7 @@ import static org.mockito.BDDMockito.*; | |||||
*/ | */ | ||||
@RunWith(SpringRunner.class) | @RunWith(SpringRunner.class) | ||||
@WebMvcTest(GatewayApiController.class) | @WebMvcTest(GatewayApiController.class) | ||||
@Import({FakeAuthServiceImpl.class, InMemApiDefinitionStore.class, AppManagement.class, SimpleMachineDiscovery.class, AuthInterceptor.class}) | |||||
@Import({FakeAuthServiceImpl.class, InMemApiDefinitionStore.class, AppManagement.class, SimpleMachineDiscovery.class, AuthorizationInterceptor.class}) | |||||
public class GatewayApiControllerTest { | public class GatewayApiControllerTest { | ||||
private static final String TEST_APP = "test_app"; | private static final String TEST_APP = "test_app"; | ||||
@@ -15,7 +15,7 @@ | |||||
*/ | */ | ||||
package com.alibaba.csp.sentinel.dashboard.controller.gateway; | package com.alibaba.csp.sentinel.dashboard.controller.gateway; | ||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthInterceptor; | |||||
import com.alibaba.csp.sentinel.dashboard.auth.AuthorizationInterceptor; | |||||
import com.alibaba.csp.sentinel.dashboard.auth.FakeAuthServiceImpl; | import com.alibaba.csp.sentinel.dashboard.auth.FakeAuthServiceImpl; | ||||
import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | import com.alibaba.csp.sentinel.dashboard.client.SentinelApiClient; | ||||
import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity; | import com.alibaba.csp.sentinel.dashboard.datasource.entity.gateway.GatewayFlowRuleEntity; | ||||
@@ -65,7 +65,7 @@ import static org.mockito.BDDMockito.*; | |||||
@RunWith(SpringRunner.class) | @RunWith(SpringRunner.class) | ||||
@WebMvcTest(GatewayFlowRuleController.class) | @WebMvcTest(GatewayFlowRuleController.class) | ||||
@Import({FakeAuthServiceImpl.class, InMemGatewayFlowRuleStore.class, AppManagement.class, SimpleMachineDiscovery.class, | @Import({FakeAuthServiceImpl.class, InMemGatewayFlowRuleStore.class, AppManagement.class, SimpleMachineDiscovery.class, | ||||
AuthInterceptor.class }) | |||||
AuthorizationInterceptor.class }) | |||||
public class GatewayFlowRuleControllerTest { | public class GatewayFlowRuleControllerTest { | ||||
private static final String TEST_APP = "test_app"; | private static final String TEST_APP = "test_app"; | ||||