【发布时间】:2014-05-08 21:18:19
【问题描述】:
我正在尝试开发具有 springs 安全性的 Springs-Hibernate 登录应用程序。当我尝试使用 Hibernate 从数据库中检索用户时。我有正常工作的 Springs-Hibernate 配置。每次 getter 返回 sessionFactory null (我在 getSessionFactory 方法中打印地址)。我有一种方法 getLoginDetails() 如果我没有在登录时调用方法(仅使用简单的锚标记检查),它可以正常工作,但是当我登录时它不起作用。这是我的代码:
Springs-security.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="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">
<!-- This is where we configure Spring-Security -->
<security:http auto-config="true" use-expressions="true" access-denied-page="/auth/denied" >
<security:intercept-url pattern="/auth/login" access="permitAll"/>
<security:intercept-url pattern="/main/admin" access="hasRole('ROLE_ADMIN')"/>
<security:intercept-url pattern="/main/common" access="hasRole('ROLE_USER')"/>
<security:form-login
login-page="/auth/login"
authentication-failure-url="/auth/hi"
authentication-success-handler-ref="myAuthenticationSuccessHandler"/>
<security:logout
invalidate-session="true"
logout-success-url="/loggedout" />
</security:http>
<!-- A custom service where Spring will retrieve users and their corresponding access levels -->
<bean id="customUserDetailsService" class="com.springs.service.CustomUserDetailsService"/>
<!--A service where spring will redirect to proper view after successfull login-->
<bean id="myAuthenticationSuccessHandler" class="com.springs.controller.MySimpleUrlAuthenticationSuccessHandler" />
<!-- Declare an authentication-manager to use a custom userDetailsService -->
<security:authentication-manager>
<security:authentication-provider user-service-ref="customUserDetailsService">
</security:authentication-provider>
</security:authentication-manager>
</beans>
ApplicationContext.xml:
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd">
<bean class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="location">
<value>classpath:jdbc.properties</value>
</property>
</bean>
<bean id="DataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close">
<property name="driverClass" value="${jdbc.driverClassName}"/>
<property name="jdbcUrl" value="${jdbc.url}"/>
<property name="user" value="${jdbc.username}"/>
<property name="password" value="${jdbc.password}"/>
<property name="acquireIncrement" value="${c3p0.acquireIncrement}" />
<property name="minPoolSize" value="${c3p0.minPoolSize}" />
<property name="maxPoolSize" value="${c3p0.maxPoolSize}" />
<property name="maxIdleTime" value="${c3p0.maxIdleTime}" />
</bean>
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
<property name="dataSource" ref="DataSource"/>
<property name="packagesToScan" value="com.hibernate.model" />
<property name="hibernateProperties">
<props>
<prop key="hibernate.dialect">org.hibernate.dialect.MySQLDialect</prop>
</props>
</property>
</bean>
<bean id="transactionManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory"/>
</bean>
</beans>
调度程序-servlet.xml
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xmlns:aop="http://www.springframework.org/schema/aop"
xmlns:tx="http://www.springframework.org/schema/tx"
xmlns:task="http://www.springframework.org/schema/task"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd
http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop-3.1.xsd
http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd
http://www.springframework.org/schema/task http://www.springframework.org/schema/task/spring-task-3.1.xsd
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd
http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc-3.1.xsd">
<bean class="org.springframework.web.servlet.mvc.support.ControllerClassNameHandlerMapping"/>
<mvc:resources mapping="/resources/**" location="/resources/" />
<!-- Scan only for @Controllers -->
<context:component-scan base-package="com.springs">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
<mvc:annotation-driven />
<tx:annotation-driven/>
<!--
Most controllers will use the ControllerClassNameHandlerMapping above, but
for the index controller we are using ParameterizableViewController, so we must
define an explicit mapping for it.
-->
<bean id="urlMapping" class="org.springframework.web.servlet.handler.SimpleUrlHandlerMapping">
<property name="mappings">
<props>
<prop key="index">indexController</prop>
</props>
</property>
</bean>
<bean id="viewResolver"
class="org.springframework.web.servlet.view.InternalResourceViewResolver"
p:prefix="/WEB-INF/jsp/"
p:suffix=".jsp" />
<!--
The index controller.
-->
<bean name="indexController"
class="org.springframework.web.servlet.mvc.ParameterizableViewController"
p:viewName="index" />
</beans>
CustomerUserDetailsService.java
package com.springs.service;
import com.hibernate.model.DbUser;
import com.springs.dao.UserDAO;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataAccessException;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@Service
@Transactional(readOnly = true)
public class CustomUserDetailsService implements UserDetailsService {
@Autowired
private UserDAO userDAO ;
@Override
public UserDetails loadUserByUsername(String username)
throws UsernameNotFoundException, DataAccessException {
UserDetails user = null;
try {
DbUser dbUser;
userDAO=new UserDAO();
dbUser = userDAO.getLoginDetails(username);
user = new User(
dbUser.getUsername(),
dbUser.getPassword().toLowerCase(),
true,
true,
true,
true,
getAuthorities(dbUser.getAccess()));
} catch (Exception e) {
System.out.println("\n\n\n\n\n");
e.printStackTrace();
throw new UsernameNotFoundException("Error in retrieving user");
}
return user;
}
public Collection<SimpleGrantedAuthority> getAuthorities(Integer access) {
List<SimpleGrantedAuthority> authList = new ArrayList<SimpleGrantedAuthority>(2);
if (access.compareTo(1) == 0) {
authList.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
} else {
authList.add(new SimpleGrantedAuthority("ROLE_USER"));
}
return authList;
}
}
UserDAO.java
@Repository
public class UserDAO {
@Autowired
private SessionFactory sessionFactory;
public SessionFactory getSessionFactory() {
System.out.println("session factory: "+sessionFactory);
return sessionFactory;
}
public void setSessionFactory(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public int getdata(String username) {
String hql = "select count(*) from Userdetails";
Userdetails u = (Userdetails) getSessionFactory().openSession().get(Userdetails.class, username);
System.out.println(u.getName());
Long l = (Long) getSessionFactory().openSession().createQuery(hql).uniqueResult();
return l.intValue();
}
public DbUser getLoginDetails(String username) {
DbUser user = new DbUser();
Userdetails u = (Userdetails) getSessionFactory().openSession().get(Userdetails.class, username);
user.setUsername(u.getName());
user.setPassword(u.getPassword());
user.getAccess();
Set userroles = u.getUserroles();
Iterator it = userroles.iterator();
while (it.hasNext()) {
Userrole ux=(Userrole) it.next();
user.setAccess(ux.getRollid());
}
System.out.println("accss is: "+user.getAccess());
System.out.println("username is: "+user.getUsername());
System.out.println("pw is "+user.getPassword());
return user;
}
}
服务器日志中的消息:
SEVERE: Servlet.service() for servlet [dispatcher] in context with path [/SpringSecurity] threw exception [Request processing failed; nested exception is java.lang.NullPointerException] with root cause
java.lang.NullPointerException
at com.springs.dao.UserDAO.getdata(UserDAO.java:42)
at com.springs.controller.testController.getUser(testController.java:31)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at org.springframework.web.method.support.InvocableHandlerMethod.invoke(InvocableHandlerMethod.java:213)
at org.springframework.web.method.support.InvocableHandlerMethod.invokeForRequest(InvocableHandlerMethod.java:126)
at org.springframework.web.servlet.mvc.method.annotation.ServletInvocableHandlerMethod.invokeAndHandle(ServletInvocableHandlerMethod.java:96)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.invokeHandlerMethod(RequestMappingHandlerAdapter.java:617)
at org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter.handleInternal(RequestMappingHandlerAdapter.java:578)
at org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:923)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:852)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:882)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:778)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
如果我在登录活动中使用 sessionFactory,我无法确定它是否为空,否则它不为空。首先,我在 xml 中缺少 tx 注释,后来我为 @Transactional 注释添加了该注释。我该如何解决这个问题?
【问题讨论】:
标签: java spring hibernate spring-security