记住我由 Spring Security 提供的功能

Posted

技术标签:

【中文标题】记住我由 Spring Security 提供的功能【英文标题】:Remember me functionality provided by Spring Security 【发布时间】:2014-07-23 18:12:18 【问题描述】:

我是 Spring Security 的新手,正在尝试实现 Spring Security 提供的“记住我”功能。我关注了几个博客,但对我没有帮助。这是我实现的示例代码,现在遇到了一些问题。

jsfspring-sec-bean-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:sec="http://www.springframework.org/schema/security"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">

<beans:bean id="navigator" name="navigator" class="com.mumz.jsfspringsec.beans.Navigator" scope="session">
</beans:bean>

<beans:bean id="loginBean" name="loginBean" class="com.mumz.jsfspringsec.beans.LoginBean" scope="prototype">
    <beans:property name="authenticationManager" ref="authenticationManager"></beans:property>
    <beans:property name="rememberMeServices" ref="rememberMeServices"></beans:property>
</beans:bean>

<beans:bean id="rememberMeServices"
    class="org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
    <beans:property name="key" value="jsfspring-sec" />
    <beans:property  name="userDetailsService" ref="userDetailsService" />
    <beans:property  name="alwaysRemember" value="true" />
    <beans:property  name="tokenValiditySeconds" value="60" />
</beans:bean>

<beans:bean id="rememberMeAuthenticationProvider"
    class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
    <beans:property name="key" value="jsfspring-sec"/>
</beans:bean>

<beans:bean id="rememberMeFilter"
    class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
    <beans:property name="rememberMeServices" ref="rememberMeServices"/>
    <beans:property name="authenticationManager" ref="authenticationManager" />
</beans:bean>

jsfspring-sec-security-config.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans
xmlns:sec="http://www.springframework.org/schema/security"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.1.xsd">

 <sec:http auto-config="true" use-expressions="true">
    <sec:intercept-url pattern="/pages/secure/**" access="hasRole('ROLE_USER')" />
    <sec:intercept-url pattern="/pages/unsecure/**" access="permitAll"/>
    <sec:intercept-url pattern="/pages/common/**" access="permitAll"/>
    <sec:intercept-url pattern="/**" access="permitAll"/>
    <sec:form-login login-page="/pages/common/login.jsf"/>
    <sec:remember-me key="jsfspring-sec" services-ref="rememberMeServices"/>
    <sec:logout
        invalidate-session="true"
        delete-cookies="JSESSIONID,SPRING_SECURITY_REMEMBER_ME_COOKIE"
        logout-success-url="/pages/common/login.jsf"></sec:logout>
</sec:http>

<sec:authentication-manager alias="authenticationManager">
    <sec:authentication-provider ref="rememberMeAuthenticationProvider"></sec:authentication-provider>
    <sec:authentication-provider >
        <sec:user-service id="userDetailsService">
            <sec:user authorities="ROLE_USER" name="admin" password="admin" />
        </sec:user-service>
    </sec:authentication-provider>
</sec:authentication-manager>

login.xhtml

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml"
xmlns:h="http://java.sun.com/jsf/html"
xmlns:f="http://java.sun.com/jsf/core"
xmlns:ui="http://java.sun.com/jsf/facelets">
<h:head>
</h:head>
<h:body>
    <div align="right" style="">
    <h:form  id="loginFormId" prependId="false">
            <div id="loginFieldsPnlId">
                <div id="loginFieldUsrContId">
                    <h:outputText id="outTxtUserNameId" value="Username:" name="outTxtUserNameNm"></h:outputText>
                    <h:inputText id="userName" required="true" value="#loginMgmtBean.userName" requiredMessage="Please enter username"></h:inputText>
                    <h:outputLabel id="outLblUserNameId" for="userName" name="outLblUserNameNm"></h:outputLabel>
                </div>
                <div id="loginFieldPassContId">
                    <h:outputText id="outTxtPasswordId" value="Password:" name="outTxtPasswordNm"></h:outputText>
                    <h:inputSecret id="password"  required="true" value="#loginMgmtBean.password" requiredMessage="Please enter password"></h:inputSecret>
                    <h:outputLabel id="outLblPasswordId" for="password" name="outLblPasswordNm"></h:outputLabel>
                </div>
                <div id="loginFieldPassContId">
                    <h:selectBooleanCheckbox id="rememberMe" value="#loginMgmtBean.rememberMe" label="Remember Me">Remember Me</h:selectBooleanCheckbox>
                </div>
            </div>
            <div id="loginBtnPanelId">
                <h:commandButton id="btnLoginId" value="Login" action="#loginMgmtBean.login" styleClass="loginPanelBtn"></h:commandButton>
                <h:commandButton id="btnCancelId" value="Cancel" action="#loginMgmtBean.cancel" styleClass="loginPanelBtn" immediate="true" update="loginFormId"></h:commandButton>
            </div>
    </h:form>
</div>
<div>
    <h:messages></h:messages>
</div>
</h:body>
</html>

LoginBean.java

import javax.faces.bean.ManagedBean;
import javax.faces.bean.ManagedProperty;
import javax.faces.bean.RequestScoped;
import javax.faces.context.FacesContext;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.RememberMeAuthenticationToken;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.RememberMeServices;

/**
 * The Class LoginBean.
 */
@ManagedBean(name = "loginMgmtBean")
@RequestScoped
public class LoginBean 

    /** The user name. */
    private String userName = null;

/** The password. */
private String password = null;

/** The remember me. */
private String rememberMe = null;

/** The authentication manager. */
@ManagedProperty(value = "#authenticationManager")
private AuthenticationManager authenticationManager = null;

/** The remember me services. */
@ManagedProperty(value = "#rememberMeServices")
private RememberMeServices rememberMeServices = null;

@ManagedProperty(value="#userDetailsService")
private UserDetailsService userDetailsService = null;
/**
 * Login.
 *
 * @return the string
 */
public String login() 
    try 
        Authentication result = null;
        if ("TRUE".equalsIgnoreCase(this.getRememberMe())) 
            UserDetails userDetails = userDetailsService.loadUserByUsername(getUserName());
            RememberMeAuthenticationToken rememberMeAuthenticationToken = new RememberMeAuthenticationToken(
                    "jsfspring-sec", userDetails,
                    userDetails.getAuthorities());
            HttpServletRequest httpServletRequest = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
            HttpServletResponse httpServletResponse = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
            rememberMeServices.loginSuccess(httpServletRequest, httpServletResponse, rememberMeAuthenticationToken);
            result = rememberMeAuthenticationToken;
         else 
            Authentication request = new UsernamePasswordAuthenticationToken(
                    this.getUserName(), this.getPassword());
            result = authenticationManager.authenticate(request);
        
        SecurityContextHolder.getContext().setAuthentication(result);
     catch (AuthenticationException e) 
        e.printStackTrace();
    
    return "Secured";


/**
 * Cancel.
 *
 * @return the string
 */
public String cancel() 
    return null;


/**
 * Logout.
 *
 * @return the string
 */
public String logout() 
    SecurityContextHolder.clearContext();
    /**
     * Delete Cookies
     */
    HttpServletRequest httpServletRequest = (HttpServletRequest)FacesContext.getCurrentInstance().getExternalContext().getRequest();
    HttpServletResponse httpServletResponse = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
    Cookie cookie = new Cookie("SPRING_SECURITY_REMEMBER_ME_COOKIE", null);
    cookie.setMaxAge(0);
    cookie.setPath(httpServletRequest.getContextPath().length() > 0 ? httpServletRequest.getContextPath() : "/");
    httpServletResponse.addCookie(cookie);
    return "loggedout";


/**
 * Gets the user name.
 *
 * @return the user name
 */
public String getUserName() 
    return userName;


/**
 * Sets the user name.
 *
 * @param userName
 *            the new user name
 */
public void setUserName(String userName) 
    this.userName = userName;


/**
 * Gets the password.
 *
 * @return the password
 */
public String getPassword() 
    return password;


/**
 * Sets the password.
 *
 * @param password
 *            the new password
 */
public void setPassword(String password) 
    this.password = password;


/**
 * Gets the remember me.
 *
 * @return the remember me
 */
public String getRememberMe() 
    return rememberMe;


/**
 * Sets the remember me.
 *
 * @param rememberMe
 *            the new remember me
 */
public void setRememberMe(String rememberMe) 
    this.rememberMe = rememberMe;


/**
 * Gets the authentication manager.
 *
 * @return the authentication manager
 */
public AuthenticationManager getAuthenticationManager() 
    return authenticationManager;


/**
 * Sets the authentication manager.
 *
 * @param authenticationManager
 *            the new authentication manager
 */
public void setAuthenticationManager(
        AuthenticationManager authenticationManager) 
    this.authenticationManager = authenticationManager;


/**
 * Gets the remember me services.
 *
 * @return the remember me services
 */
public RememberMeServices getRememberMeServices() 
    return rememberMeServices;


/**
 * Sets the remember me services.
 *
 * @param rememberMeServices
 *            the new remember me services
 */
public void setRememberMeServices(RememberMeServices rememberMeServices) 
    this.rememberMeServices = rememberMeServices;


public UserDetailsService getUserDetailsService() 
    return userDetailsService;


    public void setUserDetailsService(UserDetailsService userDetailsService) 
        this.userDetailsService = userDetailsService;
    

每当我尝试运行此代码时,我都会收到一些错误消息,指出 userDetailsS​​ervice 没有 bean 初始化。现在 userDetailsS​​ervice 指的是一个接口 org.springframework.security.core.userdetails.UserDetailsS​​ervice。另外我不确定它如何与数据库交互以进行用户 ID 和密码验证。

这是我收到的错误消息

19:42:08,387 ERROR [org.springframework.web.context.ContextLoader] (MSC service thread 1-8) Context initialization failed:     org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'rememberMeServices' defined in ServletContext resource [/WEB-INF/jsfspring-sec-bean-config.xml]:          Cannot resolve reference to bean 'userDetailsService' while setting bean property 'userDetailsService'; nested exception is         org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'userDetailsService' is defined
at     org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:328) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:106) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1317) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1076) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:517) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:456) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:291) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:222) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:288) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:563) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:872) [spring-context-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.context.support.AbstractApplicationContext.__refresh(AbstractApplicationContext.java:423) [spring-context-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java) [spring-context-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.web.context.ContextLoader.createWebApplicationContext(ContextLoader.java:276) [spring-web-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:197) [spring-web-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:47) [spring-web-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.apache.catalina.core.StandardContext.contextListenerStart(StandardContext.java:3392) [jbossweb-7.0.13.Final.jar:]
at org.apache.catalina.core.StandardContext.start(StandardContext.java:3850) [jbossweb-7.0.13.Final.jar:]
at org.jboss.as.web.deployment.WebDeploymentService.start(WebDeploymentService.java:90) [jboss-as-web-7.1.1.Final.jar:7.1.1.Final]
at     org.jboss.msc.service.ServiceControllerImpl$StartTask.startService(ServiceControllerImpl.java:1811)
at     org.jboss.msc.service.ServiceControllerImpl$StartTask.run(ServiceControllerImpl.java:1746)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(Unknown Source) [rt.jar:1.6.0_45]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(Unknown Source) [rt.jar:1.6.0_45]
at java.lang.Thread.run(Unknown Source) [rt.jar:1.6.0_45]

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'userDetailsService' is defined
at     org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:510) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1056) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:274) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at     org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:190) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
at             org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(Bean    DefinitionValueResolver.java:322) [spring-beans-3.0.2.RELEASE.jar:3.0.2.RELEASE]
    ... 24 more

更新

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:web="http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"     xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="WebApp_ID" version="3.0">
    <display-name>MyPortal</display-name>

<servlet>
    <servlet-name>Faces Servlet</servlet-name>
    <servlet-class>javax.faces.webapp.FacesServlet</servlet-class>
    <load-on-startup>1</load-on-startup>
</servlet>
<servlet-mapping>
    <servlet-name>Faces Servlet</servlet-name>
    <url-pattern>/faces/*</url-pattern>
    <url-pattern>*.jsf</url-pattern>
</servlet-mapping>
<context-param>
    <param-name>javax.faces.PROJECT_STAGE</param-name>
    <param-value>Development</param-value>
</context-param>
<context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>
        /WEB-INF/applicationContext.xml
        /WEB-INF/applicationContext-security.xml
    </param-value>
</context-param>
<context-param>
    <description>State saving method: 'client' or 'server' (=default). See JSF Specification 2.5.2</description>
    <param-name>javax.faces.STATE_SAVING_METHOD</param-name>
    <param-value>client</param-value>
</context-param>
<context-param>
    <param-name>javax.servlet.jsp.jstl.fmt.localizationContext</param-name>
    <param-value>resources.application</param-value>
</context-param>
<!-- Richfaces skin -->
<context-param>
    <param-name>org.richfaces.skin</param-name>
    <param-value>customBlueSky</param-value>
</context-param>
<context-param>
    <param-name>org.richfaces.enableControlSkinning</param-name>
    <param-value>true</param-value>
</context-param>
<context-param>
    <param-name>org.richfaces.push.jms.enabled</param-name>
    <param-value>true</param-value>
</context-param>
<error-page>
    <error-code>500</error-code>
    <location>/pages/errorPage.jsf</location>
</error-page>
<error-page>
    <exception-type>javax.faces.application.ViewExpiredException</exception-type>
    <location>/pages/login.jsf</location>
</error-page>

<filter>
    <filter-name>springSecurityFilterChain</filter-name>
    <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
</filter>
<filter-mapping>
    <filter-name>springSecurityFilterChain</filter-name>
    <url-pattern>/*</url-pattern>
    <dispatcher>FORWARD</dispatcher>
    <dispatcher>REQUEST</dispatcher>
</filter-mapping>



<!-- Add Support for Spring -->
<listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<listener>
    <listener-class>org.springframework.web.context.request.RequestContextListener</listener-class>
</listener>

<listener>
    <listener-class>com.sun.faces.config.ConfigureListener</listener-class>
</listener>

<!-- <listener> <listener-class>com.sun.xml.ws.transport.http.servlet.WSServletContextListener</listener-class> 
    </listener> -->

<!-- BIRT Support -->

<!-- Default locale setting. -->
<context-param>
    <param-name>BIRT_VIEWER_LOCALE</param-name>
    <param-value>en-US</param-value>
</context-param>

<!-- Default timezone setting. Examples: "Europe/Paris", "GMT+1". Defaults 
    to the container's timezone. -->
<context-param>
    <param-name>BIRT_VIEWER_TIMEZONE</param-name>
    <param-value></param-value>
</context-param>

<!-- Report resources directory for preview. Defaults to $birt home -->
<context-param>
    <param-name>BIRT_VIEWER_WORKING_FOLDER</param-name>
    <param-value></param-value>
</context-param>

<!-- Temporary document files directory. Defaults to $birt home/documents -->
<context-param>
    <param-name>BIRT_VIEWER_DOCUMENT_FOLDER</param-name>
    <param-value></param-value>
</context-param>

<!-- Flag whether the report resources can only be accessed under the working 
    folder. Defaults to true -->
<context-param>
    <param-name>WORKING_FOLDER_ACCESS_ONLY</param-name>
    <param-value>true</param-value>
</context-param>

<!-- Settings for how to deal with the url report path. e.g. "http://host/repo/test.rptdesign". 
    Following values are supported: <all> - All paths. <domain> - Only the paths 
    with host matches current domain. Note the comparison is literal, "127.0.0.1" 
    and "localhost" are considered as different hosts. <none> - URL paths are 
    not supported. Defaults to "domain". -->
<context-param>
    <param-name>URL_REPORT_PATH_POLICY</param-name>
    <param-value>domain</param-value>
</context-param>

<!-- Temporary image/chart directory. Defaults to $birt home/report/images -->
<context-param>
    <param-name>BIRT_VIEWER_IMAGE_DIR</param-name>
    <param-value></param-value>
</context-param>

<!-- Engine log directory. Defaults to $birt home/logs -->
<context-param>
    <param-name>BIRT_VIEWER_LOG_DIR</param-name>
    <param-value></param-value>
</context-param>

<!-- Report engine log level -->
<context-param>
    <param-name>BIRT_VIEWER_LOG_LEVEL</param-name>
    <param-value>WARNING</param-value>
</context-param>

<!-- Directory where to store all the birt report script libraries (JARs). 
    Defaults to $birt home/scriptlib -->
<context-param>
    <param-name>BIRT_VIEWER_SCRIPTLIB_DIR</param-name>
    <param-value></param-value>
</context-param>

<!-- Resource location directory. Defaults to $birt home -->
<context-param>
    <param-name>BIRT_RESOURCE_PATH</param-name>
    <param-value></param-value>
</context-param>

<!-- Preview report rows limit. An empty value means no limit. -->
<context-param>
    <param-name>BIRT_VIEWER_MAX_ROWS</param-name>
    <param-value></param-value>
</context-param>

<!-- Max cube fetch levels limit for report preview (Only used when previewing 
    a report design file using the preview pattern) -->
<context-param>
    <param-name>BIRT_VIEWER_MAX_CUBE_ROWLEVELS</param-name>
    <param-value></param-value>
</context-param>
<context-param>
    <param-name>BIRT_VIEWER_MAX_CUBE_COLUMNLEVELS</param-name>
    <param-value></param-value>
</context-param>

<!-- Memory size in MB for creating a cube. -->
<context-param>
    <param-name>BIRT_VIEWER_CUBE_MEMORY_SIZE</param-name>
    <param-value></param-value>
</context-param>

<!-- Defines the BIRT viewer configuration file -->
<context-param>
    <param-name>BIRT_VIEWER_CONFIG_FILE</param-name>
    <param-value>WEB-INF/viewer.properties</param-value>
</context-param>

<!-- Flag whether to allow server-side printing. Possible values are "ON" 
    and "OFF". Defaults to "ON". -->
<context-param>
    <param-name>BIRT_VIEWER_PRINT_SERVERSIDE</param-name>
    <param-value>ON</param-value>
</context-param>

<!-- Flag whether to force browser-optimized HTML output. Defaults to true -->
<context-param>
    <param-name>HTML_ENABLE_AGENTSTYLE_ENGINE</param-name>
    <param-value>true</param-value>
</context-param>

<!-- Filename generator class/factory to use for the exported reports. -->
<context-param>
    <param-name>BIRT_FILENAME_GENERATOR_CLASS</param-name>
    <param-value>org.eclipse.birt.report.utility.filename.DefaultFilenameGenerator</param-value>
</context-param>

<!-- Viewer Filter used to set the request character encoding to UTF-8. -->
<filter>
    <filter-name>ViewerFilter</filter-name>
    <filter-class>org.eclipse.birt.report.filter.ViewerFilter</filter-class>
</filter>
<filter-mapping>
    <filter-name>ViewerFilter</filter-name>
    <servlet-name>ViewerServlet</servlet-name>
</filter-mapping>
<filter-mapping>
    <filter-name>ViewerFilter</filter-name>
    <servlet-name>EngineServlet</servlet-name>
</filter-mapping>

<!-- Viewer Servlet Context Listener -->
<listener>
    <listener-class>org.eclipse.birt.report.listener.ViewerServletContextListener</listener-class>
</listener>

<!-- Viewer HttpSession Listener -->
<listener>
    <listener-class>org.eclipse.birt.report.listener.ViewerHttpSessionListener</listener-class>
</listener>

<!-- Viewer Servlet, Supports SOAP -->
<servlet>
    <servlet-name>ViewerServlet</servlet-name>
    <servlet-class>org.eclipse.birt.report.servlet.ViewerServlet</servlet-class>
</servlet>

<!-- Engine Servlet -->
<servlet>
    <servlet-name>EngineServlet</servlet-name>
    <servlet-class>org.eclipse.birt.report.servlet.BirtEngineServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>ViewerServlet</servlet-name>
    <url-pattern>/frameset</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>ViewerServlet</servlet-name>
    <url-pattern>/run</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>EngineServlet</servlet-name>
    <url-pattern>/preview</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>EngineServlet</servlet-name>
    <url-pattern>/download</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>EngineServlet</servlet-name>
    <url-pattern>/parameter</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>EngineServlet</servlet-name>
    <url-pattern>/document</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>EngineServlet</servlet-name>
    <url-pattern>/output</url-pattern>
</servlet-mapping>

<servlet-mapping>
    <servlet-name>EngineServlet</servlet-name>
    <url-pattern>/extract</url-pattern>
</servlet-mapping>

<servlet>
    <servlet-name>JBoss BIRT Servlet</servlet-name>
    <servlet-class>org.jboss.tools.birt.servlet.JBossBirtServlet</servlet-class>
</servlet>

<servlet-mapping>
    <servlet-name>JBoss BIRT Servlet</servlet-name>
    <url-pattern>/embed</url-pattern>
</servlet-mapping>

<jsp-config>
    <taglib>
        <taglib-uri>/birt.tld</taglib-uri>
        <taglib-location>/WEB-INF/tlds/birt.tld</taglib-location>
    </taglib>
</jsp-config>

</web-app>

【问题讨论】:

你能附上你的 web.xml 吗? @VladimírSchäfer : 请同时查看 web.xml 文件,如果有问题请告诉我。 【参考方案1】:

由于您尝试实例化接口,这就是您收到错误的原因。 尝试通过实现 UserDetailsS​​ervice 接口创建一个类,然后尝试实例化该类对象。

【讨论】:

以上是关于记住我由 Spring Security 提供的功能的主要内容,如果未能解决你的问题,请参考以下文章

Spring Security:记住我和会话数据

Spring Security实现记住我功能

手动设置spring security auth记住我

Spring WebFlux + Security - 我们有“记住我”功能吗?

没有 HttpSession 的 Spring Security 记住我服务

Spring-security 记住我的功能不起作用