dashboard: Improve authentication and authorization filter
Signed-off-by: Eric Zhao <sczyh16@gmail.com>
This commit is contained in:
parent
e8a01e2e17
commit
49861f4ad5
|
|
@ -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.
|
* <p>The Servlet filter for authentication.</p>
|
||||||
*
|
*
|
||||||
* Note:
|
* <p>Note: some urls are excluded as they needn't auth, such as:</p>
|
||||||
* Some urls are excluded as they needn't auth, such as:
|
* <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>
|
||||||
*
|
*
|
||||||
* Index url: /
|
* The excluded urls and urlSuffixes could be configured in {@code application.properties} file.
|
||||||
* Authentication request url: /login,logout
|
|
||||||
* Used for client: /registry/machine
|
|
||||||
* Static resources: htm,html,js and so on.
|
|
||||||
*
|
|
||||||
* The excluded urls and urlSuffixes are configured in application.properties
|
|
||||||
*
|
*
|
||||||
* @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.adapter.servlet.callback.WebCallbackManager;
|
||||||
import com.alibaba.csp.sentinel.dashboard.filter.AuthFilter;
|
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";
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue