2

SSL で構成されていない URL の shiro を「http」に戻すにはどうすればよいですか?

現在、ログイン URL を SSL フィルターでフックしています。

/ログイン = ssl[8443],authc

ログインすると、https のままで、HTTP に戻りません。

SslFilter 化されていない URL を HTTP に戻すにはどうすればよいですか?

4

1 に答える 1

0

フォーム認証を使用している場合は、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

于 2012-12-28T16:31:46.693 に答える