Spring Boot 实战之Filter实现简单的Http Basic认证

Spring Boot实战之Filter

本文在上一篇文章http://blog.csdn.net/sun_t89/article/details/51912905 的基础上,给每个rest接口上添加过滤器,使用过滤器实现简单的Http Basic认证

1、Filter功能

filter功能,它使用户可以改变一个 request和修改一个response. Filter 不是一个servlet,它不能产生一个response,它能够在一个request到达servlet之前预处理request,也可以在离开 servlet时处理response.换种说法,filter其实是一个”servlet chaining”(servlet 链).
一个Filter包括:
1)、在servlet被调用之前截获;
2)、在servlet被调用之前检查servlet request;
3)、根据需要修改request头和request数据;
4)、根据需要修改response头和response数据;
5)、在servlet被调用之后截获.

2、定义自己的过滤器

新增HTTPBasicAuthorizeAttribute.java

如果请求的Header中存在Authorization: Basic 头信息,且用户名密码正确,则继续原来的请求,否则返回没有权限的错误信息

package com.xiaofangtech.sunt.filter;
 
import java.io.IOException;
 
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
 
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xiaofangtech.sunt.utils.ResultMsg;
import com.xiaofangtech.sunt.utils.ResultStatusCode;
import sun.misc.BASE64Decoder;
 
@SuppressWarnings("restriction")
public class HTTPBasicAuthorizeAttribute implements Filter{
	
	private static String Name = "test";
	private static String Password = "test";
 
	@Override
	public void destroy() {
		// TODO Auto-generated method stub
		
	}
 
	@Override
	public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
			throws IOException, ServletException {
		// TODO Auto-generated method stub
		
		ResultStatusCode resultStatusCode = checkHTTPBasicAuthorize(request);
		if (resultStatusCode != ResultStatusCode.OK)
		{
			HttpServletResponse httpResponse = (HttpServletResponse) response;
			httpResponse.setCharacterEncoding("UTF-8");  
			httpResponse.setContentType("application/json; charset=utf-8"); 
			httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
 
			ObjectMapper mapper = new ObjectMapper();
			
			ResultMsg resultMsg = new ResultMsg(ResultStatusCode.PERMISSION_DENIED.getErrcode(), ResultStatusCode.PERMISSION_DENIED.getErrmsg(), null);
			httpResponse.getWriter().write(mapper.writeValueAsString(resultMsg));
			return;
		}
		else
		{
			chain.doFilter(request, response);
		}
	}
 
	@Override
	public void init(FilterConfig arg0) throws ServletException {
		// TODO Auto-generated method stub
		
	}
	
	private ResultStatusCode checkHTTPBasicAuthorize(ServletRequest request)
	{
		try
		{
			HttpServletRequest httpRequest = (HttpServletRequest)request;
			String auth = httpRequest.getHeader("Authorization");
			if ((auth != null) && (auth.length() > 6))
			{
				String HeadStr = auth.substring(0, 5).toLowerCase();
				if (HeadStr.compareTo("basic") == 0)
				{
					auth = auth.substring(6, auth.length());  
		            String decodedAuth = getFromBASE64(auth);
		            if (decodedAuth != null)
		            {
		            	String[] UserArray = decodedAuth.split(":");
		            	
		            	if (UserArray != null && UserArray.length == 2)
		            	{
		            		if (UserArray[0].compareTo(Name) == 0
			            			&& UserArray[1].compareTo(Password) == 0)
		            		{
		            			return ResultStatusCode.OK;
		            		}
		            	}
		            }
				}
			}
			return ResultStatusCode.PERMISSION_DENIED;
		}
		catch(Exception ex)
		{
			return ResultStatusCode.PERMISSION_DENIED;
		}
		
	}
	
	private String getFromBASE64(String s) {  
        if (s == null)  
            return null;  
        BASE64Decoder decoder = new BASE64Decoder();  
        try {  
            byte[] b = decoder.decodeBuffer(s);  
            return new String(b);  
        } catch (Exception e) {  
            return null;  
        }  
    }
 
}

3、在SpringRestApplication类中注册过滤器,给user/*都加上http basic认证过滤器

package com.xiaofangtech.sunt;
 
import java.util.ArrayList;
import java.util.List;
 
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.embedded.FilterRegistrationBean;
import org.springframework.context.annotation.Bean;
 
import com.xiaofangtech.sunt.filter.HTTPBasicAuthorizeAttribute;
 
@SpringBootApplication
public class SpringRestApplication {
 
	public static void main(String[] args) {
		SpringApplication.run(SpringRestApplication.class, args);
	}
	
	@Bean
    public FilterRegistrationBean  filterRegistrationBean() {
		FilterRegistrationBean registrationBean = new FilterRegistrationBean();
		HTTPBasicAuthorizeAttribute httpBasicFilter = new HTTPBasicAuthorizeAttribute();
		registrationBean.setFilter(httpBasicFilter);
		List<String> urlPatterns = new ArrayList<String>();
	    urlPatterns.add("/user/*");
	    registrationBean.setUrlPatterns(urlPatterns);
	    return registrationBean;
    }
}

4、测试

代码中固定用户名密码都为test,所以对接口进行请求时,需要添加以下认证头信息

Authorization: Basic dGVzdDp0ZXN0

dGVzdDp0ZXN0 为 test:test 经过base64编码后的结果

如果未添加认证信息或者认证信息错误,返回没有权限的错误信息

当认证信息正确,返回请求结果

当然可以!下面是一个简单的示例,演示如何在Spring Gateway中集成Spring Security: 首先,您需要在项目的pom.xml文件中添加以下依赖项: ```xml<dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-gateway</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> ``` 然后,创建一个Spring Security配置类,用于配置安全规则和认证管理器。这是一个示例配置类: ```java@Configuration@EnableWebFluxSecuritypublic class SecurityConfig { @Bean public SecurityWebFilterChain securityWebFilterChain(ServerHttpSecurity http) { return http .authorizeExchange() .pathMatchers("/api/public/**").permitAll() .anyExchange().authenticated() .and() .httpBasic() .and() .build(); } @Bean public ReactiveAuthenticationManager authenticationManager() { UserDetails user = User.withDefaultPasswordEncoder() .username("admin") .password("password") .roles("ADMIN") .build(); return new UserDetailsRepositoryReactiveAuthenticationManager(new MapReactiveUserDetailsService(user)); } } ``` 在这个配置中,我们定义了一个规则,允许访问`/api/public/**`的路径,其他路径需要进行身份验证。`UserDetailsRepositoryReactiveAuthenticationManager`用于验证用户凭据,并使用基于内存的用户存储。 接下来,创建一个Spring Gateway配置类,用于配置路由规则和过滤器。这是一个示例配置类: ```java@Configurationpublic class GatewayConfig { @Bean public RouteLocator customRouteLocator(RouteLocatorBuilder builder) { return builder.routes() .route("api_route", r -> r.path("/api/**") .filters(f -> f.filter(new AuthFilter())) .uri("http://your-backend-service")) .build(); } } ``` 在这个配置中,我们定义了一个路由规则,将以`/api/**`开头的请求转发到后端服务。我们还添加了一个名为`AuthFilter`的过滤器,用于在请求被转发之前进行身份验证。 最后,创建一个自定义过滤器类来执行身份验证逻辑。这是一个示例过滤器类: ```javapublic class AuthFilter implements GatewayFilter, Ordered { private static final String AUTHORIZATION_HEADER = "Authorization"; private static final String BEARER_PREFIX = "Bearer "; @Override public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) { String token = extractTokenFromRequest(exchange.getRequest()); if (token != null && isValidToken(token)) { // 身份验证通过,继续处理请求 return chain.filter(exchange); } else { // 身份验证失败,返回未授权的响应 exchange.getResponse().setStatusCode(HttpStatus.UNAUTHORIZED); return exchange.getResponse().setComplete(); } } private String extractTokenFromRequest(ServerHttpRequest request) { List<String> headers = request.getHeaders().get(AUTHORIZATION_HEADER); if (headers != null && !headers.isEmpty()) { String headerValue = headers.get(0); if (headerValue.startsWith(BEARER_PREFIX)) { return headerValue.substring(BEARER_PREFIX.length()); } } return null; } private boolean isValidToken(String token) { // 在此处验证token的有效性,可以根据实际需求进行实现 // 返回true表示token有效,返回false表示token无效 return true; } @Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } } ``` 在这个过滤器中,我们从请求中提取出Authorization头部中的Bearer令牌,并验证其有效性。根据实际需求,您可以自定义身份验证逻辑。 以上就是一个简单Spring Gateway集成Spring Security的示例。您可以根据自己的需求进行进一步的定制和扩展。希望对您有所帮助!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值