相关文章
更多最近更新
更多spring3MVC +spring security3 关于扩展UserDetailsService 无法注入service的疑问.
2019-03-25 13:52|来源: 网路
问题描述:
我想用的spring3MVC+spring security3 实现登录权限的扩展.即扩展UserDetailsService 以达到从持久层上控制登录信息.
但是现在的问题是我启动服务器后,登录时在UserDetailsService 中 service层的方法无法注入.
如下图
注意图中红线的地方. accountService为null.表示注入失败.
所以我想请教下大家:为什么会出现accountService为null 的问题.
我把主要的代码贴出来并在最后提供例子的下载.
首先是项目文件结构.
下面这段是继承UserDetailsService以实现持久层关联登录.
service接口
实现IAccountService的类
IAccountDao接口
实现IAccountDao接口的类
然后是springsecurity3的配置文件
问题补充: web.xml
问题补充:还是无法注入,但是其他controller是可以注入的.唯独这个UserDetailsService里无法注入~~
顺便把报错信息贴出来
问题补充:事务
还是不行..
问题补充:
去掉了这个,还是报错
accountService注入不成功.值为null
我想用的spring3MVC+spring security3 实现登录权限的扩展.即扩展UserDetailsService 以达到从持久层上控制登录信息.
但是现在的问题是我启动服务器后,登录时在UserDetailsService 中 service层的方法无法注入.
如下图
注意图中红线的地方. accountService为null.表示注入失败.
所以我想请教下大家:为什么会出现accountService为null 的问题.
我把主要的代码贴出来并在最后提供例子的下载.
首先是项目文件结构.
下面这段是继承UserDetailsService以实现持久层关联登录.
@Transactional(readOnly = true) public class UserDetailsServiceImpl implements UserDetailsService { private static final Logger logger = LoggerFactory .getLogger(UserDetailsServiceImpl.class); @Resource(name = "accountService") private IAccountService accountService; public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { logger.info("username:" + username); User user = accountService.getUserInfo(username); if (user == null) { throw new UsernameNotFoundException("用户" + username + "不存在!"); } Set<GrantedAuthority> grantedAuths = obtainGrantedAuthorities(user); boolean enabled = true; boolean accountNonExpired = true; boolean credentialsNonExpired = true; boolean accountNonLocked = true; UserDetails userDetails = new org.springframework.security.core.userdetails.User( username, user.getPassword(), enabled, accountNonExpired, credentialsNonExpired, accountNonLocked, grantedAuths); return userDetails; } private Set<GrantedAuthority> obtainGrantedAuthorities(User user) { Set<GrantedAuthority> authSet = Sets.newHashSet(); for (Role role : user.getRoleList()) { for (Authority authority : role.getAuthorityList()) { logger.info("authority is :" + authority.getPrefixedName()); authSet.add(new GrantedAuthorityImpl(authority .getPrefixedName())); } } return authSet; } }
service接口
public interface IAccountService { /** * 根据用户登录名获得对应的权限信息. */ public User getUserInfo(String userName); }
实现IAccountService的类
@Service("accountService") @Transactional public class AccountService implements IAccountService { @Resource(name="accountDao") private IAccountDao dao; private static final Logger logger = LoggerFactory .getLogger(AccountService.class); public User getUserInfo(String userName) { // 根据登录名(userName)获得对应的信息 User user = dao.getUserByloginName(userName); // 根据登录名获得对应的角色名.如 用户admin拥有"用户","管理员"这两个角色 List<Role> roleList = dao.getRoleByUserName(userName); for (int i = 0; i < roleList.size(); i++) { // 根据角色的ID查询出每个角色对应的权限. List<Authority> authorityList = dao.getAuthorityByRoleId(roleList .get(i).getId()); Role role = new Role(); // 将查询出来的权限信息放入Role中的authorityList. role.setAuthorityList(authorityList); // 对象role放入集合中 roleList.add(role); } // 将查询出来的角色信息(包含各个角色信息对应的权限信息)装入User里的roleList中. user.setRoleList(roleList); return user; } }
IAccountDao接口
public interface IAccountDao { /** * 根据loginName获得对应用户信息 * * @return */ public User getUserByloginName(String loginName); /** * 根据登录名获得对应的角色. * * @param userName * @return */ public List<Role> getRoleByUserName(String userName); /** * 根据角色ID获得对应的权限ID * * @param roleId * @return */ public List<Authority> getAuthorityByRoleId(int roleId); }
实现IAccountDao接口的类
@Repository("accountDao") public class AccountDao implements IAccountDao { private static final Logger logger = LoggerFactory.getLogger(AccountDao.class); private SimpleJdbcTemplate jdbcTemplate; @Resource(name = "dataSource") public void setDataSource(DataSource dataSource) { this.jdbcTemplate = new SimpleJdbcTemplate(dataSource); } public User getUserByloginName(String loginName) { String sql = "SELECT id,email,login_name,name,password FROM acct_user WHERE login_name = ?"; return jdbcTemplate.queryForObject(sql, new BeanPropertyRowMapper<User>(User.class), new Object[] { loginName }); } public List<Role> getRoleByUserName(String userName) { String sql = "SELECT acct_role.id,acct_role.name FROM acct_user LEFT JOIN acct_user_role ON acct_user_role.user_id=acct_user.id LEFT JOIN acct_role ON acct_role.id=acct_user_role.role_id WHERE acct_user.login_name = ?"; return jdbcTemplate.query(sql, new BeanPropertyRowMapper<Role>( Role.class), new Object[] { userName }); } public List<Authority> getAuthorityByRoleId(int roleId) { String sql = "SELECT acct_authority.id,acct_authority.name,acct_authority.url FROM acct_authority LEFT JOIN acct_role_authority ON acct_authority.id=acct_role_authority.authority_id LEFT JOIN acct_role ON acct_role.id=acct_role_authority.role_id WHERE acct_role.id= ?"; return jdbcTemplate.query(sql, new BeanPropertyRowMapper<Authority>( Authority.class), new Object[] { roleId }); }
然后是springsecurity3的配置文件
<?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:sec="http://www.springframework.org/schema/security" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd" default-lazy-init="true"> <sec:http auto-config="true" use-expressions="true" access-denied-page="/denied"> <sec:intercept-url pattern="/resources/**" filters="none" /> <sec:intercept-url pattern="/" access="isAuthenticated()" /> <sec:intercept-url pattern="/login" access="permitAll" /> <!-- <sec:intercept-url pattern="/" access="hasRole('ROLE_ADMIN')" /> --> <sec:form-login login-page="/login" authentication-failure-url="/login?error=1" default-target-url="/" /> <sec:logout invalidate-session="true" logout-success-url="/login" logout-url="/logout" /> </sec:http> <sec:authentication-manager> <sec:authentication-provider user-service-ref="customUserDetailsService"> <sec:password-encoder hash="plaintext" /> </sec:authentication-provider> </sec:authentication-manager> <bean id="customUserDetailsService" class="com.sjax.myapp.service.UserDetailsServiceImpl" /> </beans>
问题补充: web.xml
<?xml version="1.0" encoding="UTF-8"?> <web-app version="2.5" 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-app_2_5.xsd"> <!-- The definition of the Root Spring Container shared by all Servlets and Filters --> <context-param> <param-name>contextConfigLocation</param-name> <param-value> /WEB-INF/spring/application-security.xml /WEB-INF/spring/application-dataSource.xml /WEB-INF/spring/root-context.xml </param-value> </context-param> <!-- Processes application requests --> <servlet> <servlet-name>appServlet</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <init-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring/appServlet/servlet-context.xml</param-value> </init-param> <load-on-startup>1</load-on-startup> </servlet> <!-- Character Encoding filter --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> <init-param> <param-name>forceEncoding</param-name> <param-value>true</param-value> </init-param> </filter> <!-- SpringSecurity filter --> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <servlet-mapping> <servlet-name>appServlet</servlet-name> <url-pattern>/</url-pattern> </servlet-mapping> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> <dispatcher>REQUEST</dispatcher> <dispatcher>FORWARD</dispatcher> </filter-mapping> <!--Spring的ApplicationContext 载入 --> <!-- Creates the Spring Container shared by all Servlets and Filters --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Spring 刷新Introspector防止内存泄露 --> <listener> <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class> </listener> <!-- session超时定义,单位为分钟 --> <session-config> <session-timeout>20</session-timeout> </session-config> <!-- 出错页面定义 --> <error-page> <exception-type>java.lang.Throwable</exception-type> <location>/common/500.jsp</location> </error-page> <error-page> <error-code>500</error-code> <location>/common/500.jsp</location> </error-page> <error-page> <error-code>404</error-code> <location>/common/404.jsp</location> </error-page> <error-page> <error-code>403</error-code> <location>/common/403.jsp</location> </error-page> </web-app>
问题补充:还是无法注入,但是其他controller是可以注入的.唯独这个UserDetailsService里无法注入~~
顺便把报错信息贴出来
java.lang.NullPointerException com.sjax.myapp.service.UserDetailsServiceImpl.loadUserByUsername(UserDetailsServiceImpl.java:37) com.sjax.myapp.service.UserDetailsServiceImpl$$FastClassByCGLIB$$9f415683.invoke(<generated>) net.sf.cglib.proxy.MethodProxy.invoke(MethodProxy.java:191) org.springframework.aop.framework.Cglib2AopProxy$CglibMethodInvocation.invokeJoinpoint(Cglib2AopProxy.java:688) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150) org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110) org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:621) com.sjax.myapp.service.UserDetailsServiceImpl$$EnhancerByCGLIB$$fcc4b1b7.loadUserByUsername(<generated>) org.springframework.security.authentication.dao.DaoAuthenticationProvider.retrieveUser(DaoAuthenticationProvider.java:86) org.springframework.security.authentication.dao.AbstractUserDetailsAuthenticationProvider.authenticate(AbstractUserDetailsAuthenticationProvider.java:129) org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:130) org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:48) org.springframework.security.authentication.ProviderManager.doAuthentication(ProviderManager.java:148) org.springframework.security.authentication.AbstractAuthenticationManager.authenticate(AbstractAuthenticationManager.java:48) org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter.attemptAuthentication(UsernamePasswordAuthenticationFilter.java:97) org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:199) org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:105) org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79) org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:380) org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:169) org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
问题补充:事务
archy123 写道
事务注解去掉试试。。
还是不行..
问题补充:
archy123 写道
@Transactional(readOnly = true)
去掉了这个,还是报错
accountService注入不成功.值为null
相关问答
更多-
是不是有一款什么手机软件,可以很自然的拉长腿部?不是美图秀秀,有知道的不?[2022-10-20]
spring -
spring security3权限控制[2023-09-06]
我不知道你的权限是怎么控制的,比如一个新建人员的按钮,你把他新建的权限给删除了,你是怎么控制那个按钮的,security在jsp中有自己的标签,你可以用那个标签来判断用户是否有该权限,给你个例子 -
spring security3 需要哪些 jar[2023-06-12]
aopalliance-1.0.jar aspectjrt-1.5.4.jar aspectjweaver.jar commons-codec-1.3.jar commons-collections-3.2.jar commons-logging-1.1.1.jar jstl-1.1.2.jar log4j-1.2.14.jar spring-aop-2.0.8.jar spring-beans-2.0.8.jar spring-context-2.0.8.jar spring-core-2.0.8.jar ... -
struts2+spring security3 处理流程问题[2023-07-09]
如果有多个filter的话,会根据配置文件中filter的配置顺子组成一个过滤器链(FilterChain),所有的奥秘都在Filter的FilterChain中。服务器会按照web.xml中过滤器定义的先后循序组装成一条链,然后一次执行其中的doFilter()方法。执行的顺序为,执行第一个过滤器的chain.doFilter()之前的代码,第二个过滤器的chain.doFilter()之前的代码,请求的资源,第二个过滤器的chain.doFilter()之后的代码,第一个过滤器的chain.doFilt ... -
spring security3 需要哪些 jar[2022-08-24]
aopalliance-1.0.jar aspectjrt-1.5.4.jar aspectjweaver.jar commons-codec-1.3.jar commons-collections-3.2.jar commons-logging-1.1.1.jar jstl-1.1.2.jar log4j-1.2.14.jar spring-aop-2.0.8.jar spring-beans-2.0.8.jar spring-context-2.0.8.jar spring-core-2.0.8.jar ... -
spring security3权限控制[2022-11-18]
我不知道你的权限是怎么控制的,比如一个新建人员的按钮,你把他新建的权限给删除了,你是怎么控制那个按钮的,security在jsp中有自己的标签,你可以用那个标签来判断用户是否有该权限,给你个例子 AUTH_4010这个是用户的权限,你的新建按钮的权限是什么你填上去就好了 -
struts2+spring security3 处理流程问题[2022-10-28]
如果有多个filter的话,会根据 配置文件中filter的配置顺子组成一个过滤器链(FilterChain),所有的奥秘都在Filter的FilterChain中。 服务器会按照web.xml中过滤器定义的先后循序组装成一条链,然后一次执行其中的doFilter()方法。执行的顺序为,执行第一个过滤器的chain.doFilter() 之前的 代码,第二个过滤器的chain.doFilter()之前的代码,请求的资源,第二个过滤器的chain.doFilter()之后的代码,第一个过滤器的chain.do ... -
春天的英语怎么读?[2022-05-21]
spring -
听起来是csrf过滤器。 在Spring Security 4.x中,它默认激活: 从Spring Security 3.x迁移到4.x. 如果你总是得到HTTP 403,这可能是个问题。 尝试在security:http元素中禁用设置:
It sounds to be the csrf filter. In Spring Security 4.x it is activated by default: Migrating from Spring Secur ... -
登录页面中的参数名称有误,请参阅 FormLoginConfigurer#usernameParameter : 执行身份验证时查找用户名的HTTP参数。 默认为“用户名”。 FormLoginConfigurer#passwordParameter : 执行身份验证时查找密码的HTTP参数。 默认为“密码”。 更改登录页面中参数的名称或更改SecurityConfig的名称。 The parameter names in your login page are wrong, see FormLoginCo ...