read AppFuse 3-权限认证续

来源:互联网 发布:json 压缩传输 编辑:程序博客网 时间:2024/05/22 06:22

     容器启动时,调用监听器StartupListener,初始化Spring上下文环境,设置DAO type

通过LookupDAOHibernate.getRoles取得角色信息,存于application scope中。

     接着时调用UserCounterListener监听器,记录用户的登陆改变。

     然后通过容器form认证,将请求转给login.jsp

     Login.jsp静态引用loginForm.jsp,由其进行主要的权限认证工作。

     loginForm.jsp表单提交后,将请求转向/authorize

     /authorize的请求被login servlet处理

   <servlet-mapping>

      <servlet-name>login</servlet-name>

      <url-pattern>/authorize/*</url-pattern>

 </servlet-mapping>

     login servlet的真正处理者是LoginServlet。它取得usernamepassword并且加密password。初始化该servlet时取得初始参数,决定是否采用SSL、密码是否加密和加密规则等,并最后生成请求URL,交由容器认证,此时认证工作并不通过Springhibernate,而是直接通过JDBCRealm。采取这样的方式使得SSL加密只是应用于用户登陆,而其他资源认证则使用已有的权限认证系统(毕竟SSL认证是很耗费资源的)。

 

 

 

StartupListener监听器分析:

public class StartupListener extends ContextLoaderListener

    implements ServletContextListener {

    private static final Log log = LogFactory.getLog(StartupListener.class);

    public void contextInitialized(ServletContextEvent event) {

        if (log.isDebugEnabled()) {

            log.debug("initializing context...");

        }

        // call Spring's context ContextLoaderListener to initialize

        // all the context files specified in web.xml

        super.contextInitialized(event);

        ServletContext context = event.getServletContext();

        String daoType = context.getInitParameter(Constants.DAO_TYPE);

        // if daoType is not specified, use DAO as default

        if (daoType == null) {

            log.warn("No 'daoType' context carameter, using hibernate");

            daoType = Constants.DAO_TYPE_HIBERNATE;

        }

        // Orion starts Servlets before Listeners, so check if the config

        // object already exists

        Map config = (HashMap) context.getAttribute(Constants.CONFIG);

        if (config == null) {

            config = new HashMap();

        }

        // Create a config object to hold all the app config values

        config.put(Constants.DAO_TYPE, daoType);

        context.setAttribute(Constants.CONFIG, config);

        // output the retrieved values for the Init and Context Parameters

        if (log.isDebugEnabled()) {

            log.debug("daoType: " + daoType);

            log.debug("populating drop-downs...");

        }

        setupContext(context);

    }

    public static void setupContext(ServletContext context) {

        ApplicationContext ctx =

            WebApplicationContextUtils.getRequiredWebApplicationContext(context);

        LookupManager mgr = (LookupManager) ctx.getBean("lookupManager");

        // get list of possible roles

        context.setAttribute(Constants.AVAILABLE_ROLES, mgr.getAllRoles());

        if (log.isDebugEnabled()) {

            log.debug("drop-down initialization complete [OK]");

        }

    }

}

 

 

 

LoginServlet分析

public final class LoginServlet extends HttpServlet {

    private static String authURL = "j_security_check";

    private static String httpsPort = null;

    private static String httpPort = null;

    private static Boolean secure = Boolean.FALSE;

    private static String algorithm = "SHA";

    private static Boolean encrypt = Boolean.FALSE;

    private transient final Log log = LogFactory.getLog(LoginServlet.class);

    /**

     * 通过web.xml初始化端口参数

     */

         private static void initializeSchemePorts(ServletContext servletContext) {

        if (httpPort == null) {

            String portNumber =

                servletContext.getInitParameter(SslUtil.HTTP_PORT_PARAM);

            httpPort = ((portNumber == null) ? SslUtil.STD_HTTP_PORT : portNumber);

        }

        if (httpsPort == null) {

            String portNumber =

                servletContext.getInitParameter(SslUtil.HTTPS_PORT_PARAM);

            httpsPort = ((portNumber == null) ? SslUtil.STD_HTTPS_PORT

                                              : portNumber);

        }

    }

    public void init() throws ServletException {

        //web.xml中的auth_url是“j_security_check

        authURL = getInitParameter(Constants.AUTH_URL);

 

 

 

        //获得password存储于数据库的加密规则,//web.xml中的algorithm是“SHA

        algorithm = getInitParameter(Constants.ENC_ALGORITHM);

        //决定用户是否使用SSL

        secure = Boolean.valueOf(getInitParameter("isSecure"));

        //password是否被加密

        encrypt = Boolean.valueOf(getInitParameter("encrypt-password"));

        //默认设置

        //Use SSL for login? False

        //Programmatic encryption of password ? true

        //Use SSL for login? False

        //HTTP Port: 8080

        //HTTPS Port: 8443

        ServletContext ctx = getServletContext();

        initializeSchemePorts(ctx);

        // Orion starts Servlets before Listeners, so check if the config

        // object already exists

        Map config = (HashMap) ctx.getAttribute(Constants.CONFIG);

        if (config == null) {

            config = new HashMap();

        }

        // update the config object with the init-params from this servlet

        config.put(Constants.HTTP_PORT, httpPort);

        config.put(Constants.HTTPS_PORT, httpsPort);

        config.put(Constants.SECURE_LOGIN, secure);

        config.put(Constants.ENC_ALGORITHM, algorithm);

        config.put(Constants.ENCRYPT_PASSWORD, encrypt);

        ctx.setAttribute(Constants.CONFIG, config);

    }

    public void doGet(HttpServletRequest request, HttpServletResponse response)

    throws IOException, ServletException {

        execute(request, response);

    }

    public void doPost(HttpServletRequest request, HttpServletResponse response)

    throws IOException, ServletException {

        execute(request, response);

    }

    public void execute(HttpServletRequest request, HttpServletResponse response)

    throws IOException, ServletException {

        // 如果用户已经登陆,直接转向mainMenu.html

        if (request.getRemoteUser() != null) {

            if (log.isDebugEnabled()) {

                log.debug("User '" + request.getRemoteUser() +

                          "' already logged in, routing to mainMenu");

            }

            response.sendRedirect(request.getContextPath() + "/mainMenu.html");

            return;

        }

        String redirectString =

            SslUtil.getRedirectString(request, getServletContext(),

                                      secure.booleanValue());

        if (redirectString != null) {

            // Redirect the page to the desired URL

            response.sendRedirect(response.encodeRedirectURL(redirectString));

            if (log.isDebugEnabled()) {

                log.debug("switching protocols, redirecting user");

            }

        }

        //appfuse默认不使用SSL,会执行下面的程序。

        String username = request.getParameter("j_username");

        String password = request.getParameter("j_password");

        //记录用户信息在Cookies中。

        if (request.getParameter("rememberMe") != null) {

            request.getSession().setAttribute(Constants.LOGIN_COOKIE, "true");

        }

        String encryptedPassword = "";

        if (encrypt.booleanValue() &&

                (request.getAttribute("encrypt") == null)) {

            if (log.isDebugEnabled()) {

                log.debug("Encrypting password for user '" + username + "'");

            }

            //加密password

            encryptedPassword = StringUtil.encodePassword(password, algorithm);

        } else {

            encryptedPassword = password;

        }

        if (redirectString == null) {

            // signifies already correct protocol

            if (log.isDebugEnabled()) {

                log.debug("Authenticating user '" + username + "'");

            }

            String req =

                request.getContextPath() + "/" + authURL + "?j_username=" +

                username + "&j_password=" + encryptedPassword + "&j_uri=" +

                request.getParameter("j_uri");

// URL : //'/dudu/j_security_check?j_username=mraible&j_password=536c0b339345616c1b33caf4544//54d8b8a19 0d6c&j_uri=’

            if (log.isDebugEnabled()) {

                log.debug("URL : '" + req + "'");

            }

            response.sendRedirect(response.encodeRedirectURL(req));

        }

    }

}

 

 

 

原创粉丝点击