对于没有配置 SSL 的 URL,如何让 shiro 改回“http”?
目前,我的登录网址与 SSL 过滤器挂钩。
/登录 = ssl[8443],authc
当我登录时,它停留在 https,并且不会切换回 HTTP。
对于未经过 SslFilter'ized 的 URL,如何使其恢复为 HTTP?
如果您使用表单身份验证,您可以通过扩展 FormAuthenticationFilter 并重定向到非 https URL 来自定义“登录时”行为。
这是一个例子:
package example.shiro;
import java.net.MalformedURLException;
import java.net.URL;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.authc.FormAuthenticationFilter;
import org.apache.shiro.web.filter.authz.PortFilter;
import org.apache.shiro.web.filter.authz.SslFilter;
import org.apache.shiro.web.util.SavedRequest;
import org.apache.shiro.web.util.WebUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class AuthenticatingFilter extends FormAuthenticationFilter {
private static Logger logger = LoggerFactory.getLogger( AuthenticatingFilter.class );
private int port = PortFilter.DEFAULT_HTTP_PORT;
private String indexUrl = "/";
public void setPort( int port ) {
this.port = port;
}
public void setIndexUrl( String indexUrl ) {
this.indexUrl = indexUrl;
}
@Override
protected boolean onLoginSuccess( AuthenticationToken token, Subject subject, ServletRequest request, ServletResponse response ) throws Exception {
boolean result = true;
String reqScheme = request.getScheme();
if( SslFilter.HTTPS_SCHEME.equals( reqScheme ) ) {
HttpServletRequest httpReq = null;
if( request instanceof HttpServletRequest ) {
httpReq = WebUtils.toHttp( request );
String uri;
String query;
SavedRequest savedRequest = WebUtils.getSavedRequest( request );
if( savedRequest == null ) {
uri = httpReq.getRequestURI();
query = httpReq.getQueryString();
}
else {
uri = savedRequest.getRequestURI();
query = savedRequest.getQueryString();
}
String redirectUrl = fromHttps( httpReq, uri, query );
WebUtils.issueRedirect( request, response, redirectUrl, null, false );
result = false;
}
else {
if( logger.isWarnEnabled() ) {
logger.warn( "request is not an instance of HttpServletRequest: {}", request.getClass().toString() );
}
result = true;
}
}
else {
result = super.onLoginSuccess( token, subject, request, response );
}
return result;
}
private String fromHttps( HttpServletRequest request, String uri, String query ) {
StringBuilder sb = new StringBuilder();
try {
URL originalURL = new URL( request.getRequestURL().toString() );
sb.append( PortFilter.HTTP_SCHEME );
sb.append( "://" );
sb.append( originalURL.getHost() );
if( originalURL.getPort() != port && port != PortFilter.DEFAULT_HTTP_PORT ) {
sb.append( ":" );
sb.append( port );
}
String path = originalURL.getPath();
int semiPos = path.indexOf( ";" ); // if there was pathParameter data it should have been on the original request, it sometimes seems be missing from request.getPathInfo()?
String pathParameters = "";
if( semiPos > 0 ) {
pathParameters = path.substring( semiPos );
}
semiPos = uri.indexOf( ";" ); // pathParameter data may be present on uri (from a saved request), if so, throw it away as it may be from a bookmark
if( semiPos > 0 ) {
uri = uri.substring( 0, semiPos );
}
if( uri.endsWith( getLoginUrl() ) ) {
int loginPos = uri.indexOf( getLoginUrl() );
String contextPath = uri.substring( 0, loginPos );
sb.append( contextPath );
sb.append( indexUrl );
}
else {
sb.append( uri );
}
sb.append( pathParameters );
if( query != null ) {
sb.append( "?" ).append( query );
}
if( logger.isTraceEnabled() ) {
logger.trace( "redirect url is : {}", sb.toString() );
}
}
catch( MalformedURLException e ) {
logger.error( "cannot construct request URL", e );
}
return sb.toString();
}
}
您还需要 shiro.ini 中的一些相应条目:
[main]
authc = example.shiro.AuthenticatingFilter
authc.loginUrl = /somepath/login
authc.port = 8080
authc.indexUrl = /somepath/index
[urls]
/somepath/index = anon
/somepath/login = ssl[8443], authc
这个提议的解决方案远非完美,但可以在我正在使用的堆栈中完成工作(shiro、jersey、tomcat),如果你能找到更好和/或更通用的解决方法,请分享它!
干杯,
JJB