SSL で構成されていない URL の shiro を「http」に戻すにはどうすればよいですか?
現在、ログイン URL を SSL フィルターでフックしています。
/ログイン = ssl[8443],authc
ログインすると、https のままで、HTTP に戻りません。
SslFilter 化されていない 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