原文: https://howtodoinjava.com/spring-security/custom-userdetailsservice-example-for-spring-3-security/

学习在 Spring 应用程序的authentication-provider中自定义UserDetailsService实现,以获取自定义User对象,以及如何在应用程序中使用它。

Spring UserDetailsService接口

UserDetailsService 界面用于为任何给定用户查找用户名,密码和 GrantedAuthorities

此接口仅提供实现类需要实现的一种方法:

UserDetailsService.java

  1. UserDetails loadUserByUsername(String username) throws UsernameNotFoundException;

这里 UserDetails 是核心用户信息的容器。 根据文档,出于安全目的,Spring Security 不会直接使用其实现。 它们只是存储用户信息,这些信息随后封装到 Authentication 对象中。 这允许将与安全无关的用户信息(例如电子邮件地址,电话号码等)存储在方便的位置。 一个非常好的示例实现可以类似于 User 类。

在此示例中, AuthenticationProvider 只需通过将 UsernamePasswordAuthenticationToken 中提交的密码与UserDetailsService加载的密码进行比较,即可对用户进行身份验证。

UserDetailsService实现

1)配置身份验证供应器

我正在提出基于 Spring 登录表单的安全性中编写的代码库。 在application-security.xml文件中,我将更新配置以将EmployeeDao用作自定义用户详细信息服务。

application-security.xml

  1. < ?xml version="1.0" encoding="UTF-8"?>
  2. <beans:beans xmlns="http://www.springframework.org/schema/security"
  3. xmlns:beans="http://www.springframework.org/schema/beans"
  4. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  5. xsi:schemaLocation="http://www.springframework.org/schema/beans
  6. http://www.springframework.org/schema/beans/spring-beans-3.0.xsd
  7. http://www.springframework.org/schema/security
  8. http://www.springframework.org/schema/security/spring-security-3.0.3.xsd">
  9. <http auto-config="true" use-expressions="true">
  10. <intercept-url pattern="/login" access="permitAll"></intercept-url>
  11. <intercept-url pattern="/logout" access="permitAll"></intercept-url>
  12. <intercept-url pattern="/accessdenied" access="permitAll"></intercept-url>
  13. <intercept-url pattern="/**" access="hasRole('ROLE_USER')"></intercept-url>
  14. <form-login login-page="/login" default-target-url="/list" authentication-failure-url="/accessdenied"></form-login>
  15. <logout logout-success-url="/logout"></logout>
  16. </http>
  17. <authentication-manager alias="authenticationManager">
  18. <authentication-provider user-service-ref="employeeDAO" />
  19. </authentication-manager>
  20. </beans:beans>

2)配置数据源

另外,完整的employee-servlet.xml文件如下所示:

employee-servlet.xml

  1. < ?xml version="1.0" encoding="UTF-8"?>
  2. <beans xmlns="http://www.springframework.org/schema/beans"
  3. xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  4. xmlns:aop="http://www.springframework.org/schema/aop"
  5. xmlns:context="http://www.springframework.org/schema/context"
  6. xmlns:jee="http://www.springframework.org/schema/jee"
  7. xmlns:lang="http://www.springframework.org/schema/lang"
  8. xmlns:p="http://www.springframework.org/schema/p"
  9. xmlns:tx="http://www.springframework.org/schema/tx"
  10. xmlns:util="http://www.springframework.org/schema/util"
  11. xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
  12. http://www.springframework.org/schema/aop/ http://www.springframework.org/schema/aop/spring-aop.xsd
  13. http://www.springframework.org/schema/context/ http://www.springframework.org/schema/context/spring-context.xsd
  14. http://www.springframework.org/schema/jee/ http://www.springframework.org/schema/jee/spring-jee.xsd
  15. http://www.springframework.org/schema/lang/ http://www.springframework.org/schema/lang/spring-lang.xsd
  16. http://www.springframework.org/schema/tx/ http://www.springframework.org/schema/tx/spring-tx.xsd
  17. http://www.springframework.org/schema/util/ http://www.springframework.org/schema/util/spring-util.xsd">
  18. <context:annotation-config />
  19. <context:component-scan base-package="com.howtodoinjava.controller" />
  20. <bean id="jspViewResolver"
  21. class="org.springframework.web.servlet.view.InternalResourceViewResolver">
  22. <property name="viewClass"
  23. value="org.springframework.web.servlet.view.JstlView"></property>
  24. <property name="prefix" value="/WEB-INF/view/"></property>
  25. <property name="suffix" value=".jsp"></property>
  26. </bean>
  27. <bean id="messageSource"
  28. class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
  29. <property name="basename" value="classpath:messages"></property>
  30. <property name="defaultEncoding" value="UTF-8"></property>
  31. </bean>
  32. <bean id="propertyConfigurer"
  33. class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer"
  34. p:location="/WEB-INF/jdbc.properties"></bean>
  35. <bean id="dataSource"
  36. class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close"
  37. p:driverClassName="${jdbc.driverClassName}"
  38. p:url="${jdbc.databaseurl}" p:username="${jdbc.username}"
  39. p:password="${jdbc.password}"></bean>
  40. <bean id="sessionFactory"
  41. class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
  42. <property name="dataSource" ref="dataSource"></property>
  43. <property name="configLocation">
  44. <value>classpath:hibernate.cfg.xml</value>
  45. </property>
  46. <property name="configurationClass">
  47. <value>org.hibernate.cfg.AnnotationConfiguration</value>
  48. </property>
  49. <property name="hibernateProperties">
  50. <value>
  51. hibernate.connection.provider_class=org.hibernate.connection.C3P0ConnectionProvider
  52. hibernate.dialect=org.hibernate.dialect.SQLServer2008Dialect
  53. hibernate.default_schema=dbo
  54. hibernate.show_sql=true
  55. </value>
  56. </property>
  57. </bean>
  58. <bean id="employeeDAO" class="com.howtodoinjava.dao.EmployeeDaoImpl"></bean>
  59. <bean id="employeeManager" class="com.howtodoinjava.service.EmployeeManagerImpl"></bean>
  60. <tx:annotation-driven />
  61. <bean id="transactionManager"
  62. class="org.springframework.orm.hibernate3.HibernateTransactionManager">
  63. <property name="sessionFactory" ref="sessionFactory"></property>
  64. </bean>
  65. </beans>

3)在 Dao 中实现UserDetailsService

现在,我们必须更新EmployeeDaoImpl.java以实现UserDetailsService接口和重写方法loadUserByUsername()

EmployeeDaoImpl.java

EmployeeDaoImpl.java

  1. package com.howtodoinjava.dao;
  2. import java.util.List;
  3. import org.hibernate.SessionFactory;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.dao.DataAccessException;
  6. import org.springframework.security.core.GrantedAuthority;
  7. import org.springframework.security.core.authority.GrantedAuthorityImpl;
  8. import org.springframework.security.core.userdetails.User;
  9. import org.springframework.security.core.userdetails.UserDetails;
  10. import org.springframework.security.core.userdetails.UserDetailsService;
  11. import org.springframework.security.core.userdetails.UsernameNotFoundException;
  12. import org.springframework.stereotype.Repository;
  13. import com.howtodoinjava.entity.EmployeeEntity;
  14. @Repository
  15. public class EmployeeDaoImpl implements EmployeeDAO, UserDetailsService {
  16. @Autowired
  17. private SessionFactory sessionFactory;
  18. @Override
  19. public void addEmployee(EmployeeEntity employee) {
  20. this.sessionFactory.getCurrentSession().save(employee);
  21. }
  22. @SuppressWarnings("unchecked")
  23. @Override
  24. public List<EmployeeEntity> getAllEmployees() {
  25. return this.sessionFactory.getCurrentSession().createQuery("from Employee").list();
  26. }
  27. @Override
  28. public void deleteEmployee(Integer employeeId) {
  29. EmployeeEntity employee = (EmployeeEntity) sessionFactory.getCurrentSession().load(
  30. EmployeeEntity.class, employeeId);
  31. if (null != employee) {
  32. this.sessionFactory.getCurrentSession().delete(employee);
  33. }
  34. }
  35. @SuppressWarnings("deprecation")
  36. @Override
  37. public UserDetails loadUserByUsername(String username)
  38. throws UsernameNotFoundException, DataAccessException
  39. {
  40. System.out.println("Getting access details from employee dao !!");
  41. // Ideally it should be fetched from database and populated instance of
  42. // #org.springframework.security.core.userdetails.User should be returned from this method
  43. UserDetails user = new User(username, "password", true, true, true, true, new GrantedAuthority[]{ new GrantedAuthorityImpl("ROLE_USER") });
  44. return user;
  45. }
  46. }

在上面的 Dao 中,我使用了最少的代码来演示所涉及的类的用法,并且在企业应用程序中,应该对数据库进行适当的访问,并且应该设置用户的密码及其角色。

整个想法是用方法内部的填充值返回User实例。 如果您还有其他要求,那么您也可以自由实现UserDetails接口,并且 spring 不会阻止您使用它。

示例

要测试该应用程序,只需在浏览器窗口中单击 URL “http://localhost:8080/Spring3HibernateIntegration”。 一个登录框将如下所示:

Spring Security `UserDetailsS​​ervice`示例 - 图1

现在,使用正确的用户名和密码(即lokeshpassword)登录,您可以进入应用程序,并出现员工管理屏幕。 否则,访问被拒绝的页面将显示如下:

Spring Security `UserDetailsS​​ervice`示例 - 图2

下载源码

学习愉快!