NullPointerException从SpringBean上记住我
我正在使用本教程学习spring安全性的基础知识,目前已到达第页(使用自定义数据库实现和JSF 2.0的spring安全性3.1身份验证)。问题是,尽管我复制了他博客上写的所有内容,但如果我尝试登录时选中了“记住我”,我仍然会收到NullPointerException。正如我所看到的,这是由“LoginBean”中的变量“userDetailsService”引起的。我得到: 有人能帮忙吗 编辑: web.xmlNullPointerException从SpringBean上记住我,spring,security,jsf,nullpointerexception,remember-me,Spring,Security,Jsf,Nullpointerexception,Remember Me,我正在使用本教程学习spring安全性的基础知识,目前已到达第页(使用自定义数据库实现和JSF 2.0的spring安全性3.1身份验证)。问题是,尽管我复制了他博客上写的所有内容,但如果我尝试登录时选中了“记住我”,我仍然会收到NullPointerException。正如我所看到的,这是由“LoginBean”中的变量“userDetailsService”引起的。我得到: 有人能帮忙吗 编辑: web.xml <?xml version="1.0" encoding="UTF-8"?
<?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_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- CONFIGURATION FILES both Bean definition and security -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/resources/CONFIGURATION/SPRING/BEANDEFINITION/jsfspring-sec-bean-config.xml
/resources/CONFIGURATION/SPRING/SECURITY/jsfspring-sec-security-config.xml
</param-value>
</context-param>
<!-- CONFIGURATION FILES END HERE -->
<!-- PROJECT STAGE START FOR DEVELOPEMENT MARK IT AS DEVELOPMENT, FOR TESTING,
UAT, PRODUCTION REMOVE THIS -->
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<!-- PROJECT STAGE END -->
<!-- Enable JSF Servlet -->
<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>*.jsf</url-pattern>
</servlet-mapping>
<!-- Enable JSF Server End -->
<!-- Integrate JSF and Spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Integrate JSF and Spring End -->
<!-- Enable Spring Filter, Spring Security works on the concept of Filters -->
<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>
</filter-mapping>
<!-- Enable Spring Filter End -->
<!-- Welcome File -->
<welcome-file-list>
<welcome-file>/pages/index/index.jsp</welcome-file>
</welcome-file-list>
<!-- Welcome File End -->
</web-app>
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>
记得我吗
我找到了解决方案。我在jsfspring-sec-bean-config.xml和jsfspring-sec-security-config.xml中将“customjdbcUserService”更改为“userDetailsService”,现在userDetailsService从数据库中获取正确的值,因此不再为空。您可以发布您的代码吗?如果愿意,可以在链接中提供更多详细信息。谢谢。我不知道与Spring相关的东西,但您是否尝试过删除UserDetailsService的“=null”是的,但它仍然引发异常。您提出问题的方式表明您已经不知道如何以及为什么会导致java.lang.NullPointerException
。我建议暂停一下JavaEE,先学习基本Java。java.lang.*
包中的异常表示基本的java问题。
<?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_3_0.xsd"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd"
version="3.0">
<!-- CONFIGURATION FILES both Bean definition and security -->
<context-param>
<param-name>contextConfigLocation</param-name>
<param-value>
/resources/CONFIGURATION/SPRING/BEANDEFINITION/jsfspring-sec-bean-config.xml
/resources/CONFIGURATION/SPRING/SECURITY/jsfspring-sec-security-config.xml
</param-value>
</context-param>
<!-- CONFIGURATION FILES END HERE -->
<!-- PROJECT STAGE START FOR DEVELOPEMENT MARK IT AS DEVELOPMENT, FOR TESTING,
UAT, PRODUCTION REMOVE THIS -->
<context-param>
<param-name>javax.faces.PROJECT_STAGE</param-name>
<param-value>Development</param-value>
</context-param>
<!-- PROJECT STAGE END -->
<!-- Enable JSF Servlet -->
<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>*.jsf</url-pattern>
</servlet-mapping>
<!-- Enable JSF Server End -->
<!-- Integrate JSF and Spring -->
<listener>
<listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
</listener>
<!-- Integrate JSF and Spring End -->
<!-- Enable Spring Filter, Spring Security works on the concept of Filters -->
<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>
</filter-mapping>
<!-- Enable Spring Filter End -->
<!-- Welcome File -->
<welcome-file-list>
<welcome-file>/pages/index/index.jsp</welcome-file>
</welcome-file-list>
<!-- Welcome File End -->
</web-app>
<?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:property name="userDetailsService" ref="customjdbcUserService"></beans:property>
</beans:bean>
<beans:bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<beans:property name="driverClassName" value="com.mysql.jdbc.Driver" />
<beans:property name="url"
value="jdbc:mysql://localhost:3306/jsf-spring-security" />
<beans:property name="username" value="root" />
<beans:property name="password" value="root" />
</beans:bean>
<beans:bean id="customjdbcUserService" class="com.mumz.jsfspringsec.dao.CustomJDBCDaoImpl">
<beans:property name="dataSource" ref="dataSource" />
<beans:property name="enableAuthorities" value="true" />
<beans:property name="usersByUsernameQuery">
<beans:value>
SELECT JSF_SPRING_SEC_USERS_USERNAME,JSF_SPRING_SEC_USERS_PASSWORD, JSF_SPRING_SEC_USERS_ENABLED FROM JSF_SPRING_SEC_USERS WHERE JSF_SPRING_SEC_USERS_USERNAME = ?
</beans:value>
</beans:property>
<beans:property name="authoritiesByUsernameQuery">
<beans:value>
select JSF_SPRING_SEC_ROLES_USERNAME,JSF_SPRING_SEC_ROLES_ROLE_NAME from JSF_SPRING_SEC_ROLES where JSF_SPRING_SEC_ROLES_USERNAME = ?
</beans:value>
</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="customjdbcUserService" />
<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>
</beans:beans>
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:sec="http://www.springframework.org/schema/security" 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
user-service-ref="customjdbcUserService">
</sec:authentication-provider>
</sec:authentication-manager>
</beans:beans>
<?xml version="1.0" encoding="UTF-8"?>
<faces-config
xmlns="http://java.sun.com/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-facesconfig_2_0.xsd"
version="2.0">
<!-- Enable Spring -->
<application>
<el-resolver>org.springframework.web.jsf.el.SpringBeanFacesELResolver</el-resolver>
</application>
<!-- Simple Navigation Rule -->
<!-- If user keys in ToSecure, move to /pages/secure/secured.xhtml-->
<!-- Else If user keys in ToUnSecure, move to /pages/unsecure/unsecured.xhtml-->
<navigation-rule>
<display-name>pages/home/home.xhtml</display-name>
<from-view-id>/pages/home/home.xhtml</from-view-id>
<navigation-case>
<from-action>#{navigator.navigateTo}</from-action>
<from-outcome>Secured</from-outcome>
<to-view-id>/pages/secure/secured.xhtml</to-view-id>
<redirect></redirect>
</navigation-case>
</navigation-rule>
<navigation-rule>
<display-name>pages/home/home.xhtml</display-name>
<from-view-id>/pages/home/home.xhtml</from-view-id>
<navigation-case>
<from-action>#{navigator.navigateTo}</from-action>
<from-outcome>UnSecured</from-outcome>
<to-view-id>/pages/unsecure/unsecured.xhtml</to-view-id>
<redirect></redirect>
</navigation-case>
</navigation-rule>
<navigation-rule>
<display-name>pages/secure/secured.xhtml</display-name>
<from-view-id>/pages/secure/secured.xhtml</from-view-id>
<navigation-case>
<from-action>#{loginMgmtBean.logout}</from-action>
<from-outcome>loggedout</from-outcome>
<to-view-id>/pages/home/home.xhtml</to-view-id>
<redirect></redirect>
</navigation-case>
</navigation-rule>
<navigation-rule>
<display-name>pages/common/login.xhtml</display-name>
<from-view-id>/pages/common/login.xhtml</from-view-id>
<navigation-case>
<from-action>#{loginMgmtBean.login}</from-action>
<from-outcome>Secured</from-outcome>
<to-view-id>/pages/secure/secured.xhtml</to-view-id>
</navigation-case>
</navigation-rule>
</faces-config>
package com.mumz.jsfspringsec.beans;
import java.io.Serializable;
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 implements Serializable {
/**
*
*/
private static final long serialVersionUID = 1L;
/** 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 "Fail";
}
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;
}
}
<!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>