【问题标题】:How to configure Spring Security with Hibernate and XML如何使用 Hibernate 和 XML 配置 Spring Security
【发布时间】:2018-01-31 07:29:36
【问题描述】:

我已经在我的项目中配置了 Spring Security,并且在使用默认表单时可以按预期工作,隐藏特定页面。但是当我创建自己的登录表单时,用户没有角色,因此页面仍然隐藏,因为我将 XML 配置为仅向经过身份验证的用户显示页面。

我有一个具有 id、用户名、密码、角色属性的实体类(管理员)(我现在不想使用第二个表“角色”)。

我已经阅读了很多教程,其他人建议实体类应该实现 UserDetails 或创建一个实现 UserDetailsS​​ervice 的 MyUserDetailsS​​ervice。为什么我需要这样做?

无论如何,我尝试了我阅读的所有内容,但没有得到任何结果。即使我登录,受保护的页面仍然隐藏。我只需要登录的管理员拥有 ROLE_ADMIN(或 ROLE_MODERATOR,因为这些是他们在注册时可以选择的唯一选项),以便他们能够访问受保护的页面(/admin/list)。

我研究了这个链接Spring Security+Hibernate+XML 据我了解,我必须在 spring-security.xml 中更改这些行,如下代码所示:

<authentication-manager>
    <authentication-provider user-service-ref="myUserDetailsService" >
    </authentication-provider>
</authentication-manager>

那么当我只有一个管理员表并且我只想在登录时授予他们的角色时,我将如何创建 UserDetailsS​​ervice 的新实现?

谢谢。

管理员类

@Entity
@Table(name="administrator")
public class Administrator {

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="administrator_id")
private int id;

@NotNull(message="is required")
@Size(min=6, message="minimum chars 6")
@Size(max=45, message="maximum chars 45")
@Column(name="username")
private String username;

@NotNull(message="is required")
@Size(min=6, message="minimum chars 6")
@Size(max=45, message="maximum chars 45")
@Column(name="password")
private String password;

@Column(name="role")
private String role;

// Class constructor
public Administrator() {

}

// Getters and setters

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

public String getUsername() {
    return username;
}

public void setUsername(String username) {
    this.username = username;
}

public String getPassword() {
    return password;
}

public void setPassword(String password) {
    this.password = password;
}

public String getRole() {
    return role;
}

public void setRole(String role) {
    this.role = role;
}

web.xml

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" 
xmlns="http://xmlns.jcp.org/xml/ns/javaee" 
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee 
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" id="WebApp_ID" 
version="3.1">
<display-name>platform</display-name>

<welcome-file-list>
  <welcome-file>index.jsp</welcome-file>
  <welcome-file>index.html</welcome-file>
</welcome-file-list>

<!-- Listener for multiple xml configuration files -->

<listener>
  <listener-
class>org.springframework.web.context.ContextLoaderListener</listener-
class>
</listener>

<context-param>
  <param-name>contextConfigLocation</param-name>
  <param-value>
      /WEB-INF/platform-servlet.xml,
      /WEB-INF/spring-security.xml
  </param-value>
</context-param>

<servlet>
  <servlet-name>dispatcher</servlet-name>
  <servlet-
class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
<init-param>
    <param-name>contextConfigLocation</param-name>
    <param-value></param-value>
</init-param>
<load-on-startup>1</load-on-startup>

<!-- Turn on async support for servlet -->
<async-supported>true</async-supported>

</servlet>

<servlet-mapping>
  <servlet-name>dispatcher</servlet-name>
  <url-pattern>/</url-pattern>
</servlet-mapping>

<!-- Add filter for Spring security mapping -->

<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>

spring-security.xml

<beans:beans xmlns="http://www.springframework.org/schema/security"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans.xsd
       http://www.springframework.org/schema/security
       http://www.springframework.org/schema/security/spring-security.xsd">

  <http auto-config="true" use-expressions="true">
    <!-- <intercept-url pattern="/admin/list" access="hasRole('ROLE_ADMIN')" /> -->
    <intercept-url pattern="/home/login-page" access="isAnonymous()" />
    <intercept-url pattern="/admin/list" access="isAuthenticated()" />

    <form-login
        login-page="/home/login-page"
        default-target-url="/home/main"
        authentication-failure-url="/home/login-page"
        login-processing-url="/login-process" />

    <logout logout-success-url="/home/login-page"/>

  </http>

  <authentication-manager>
    <authentication-provider>
        <user-service>
            <user name="user111" password="pass111" authorities="ROLE_USER" />
        </user-service>
    </authentication-provider>
  </authentication-manager>

</beans:beans>

【问题讨论】:

标签: xml spring hibernate spring-mvc spring-security


【解决方案1】:

首先,您不需要在 web.xml 文件中添加“身份验证管理器”。您必须创建一个扩展 WebSecurityConfigurerAdapter 的 SecurityConfiguration 类。从那里您可以创建 InMemoryUserDetailsManager bean,如下所示:

// Bean that holds all authenticated users + new ones during runtime
@Bean
public InMemoryUserDetailsManager inMemoryUserDetailsManager() {

final Properties users = new Properties();

    // Get all administrators from the service
    List<Administrator> theAdministrators = administratorService.getAdministrators();

    // Iterate list and save current username, password and role

    for (int i = 0; i < theAdministrators.size(); i++) {

        // Get current attributes from administrator object

        String currentUsername = theAdministrators.get(i).getUsername();
        String encryptedPassword = theAdministrators.get(i).getPassword();
        String currentRole = theAdministrators.get(i).getRole();

        // Decrypt current password
        String currentPassword = strongTextEncryptorHelper.decryptPassword(encryptedPassword);

        // Authenticate all administrators in memory and grant them their roles
        users.put(currentUsername, currentPassword + ", " + "ROLE_" + currentRole + ", " + "enabled");
    }

    // Return authenticated users + new ones during runtime
    return new InMemoryUserDetailsManager(users);
}

@Autowired
public void configureGlobalSecurity(AuthenticationManagerBuilder auth) throws Exception {

    // Authenticate administrators in memory, with user details service
    auth.userDetailsService(inMemoryUserDetailsManager());
}

然后,您可以通过将路径添加到适当的 antMatchers() 方法来保护 webapp 的特定页面:

protected void configure(HttpSecurity http) throws Exception {


    // Make login page and oauth token accessible without authentication
    // Protect all pages and allow only admins and moderators to access them

    http.csrf().disable()
        .authorizeRequests()        
        .antMatchers("/home/login-page").permitAll()
        .antMatchers("/oauth/token").permitAll()
            .antMatchers("/home/**", "/admin/**"")
            .access("hasAnyRole('ADMIN', 'MODERATOR')")
            .and()
            .formLogin()
            .loginPage("/home/login-page")
            .defaultSuccessUrl("/home/main", true)
            .failureUrl("/home/login-page?fail=Invalid+login+details")
            .and()
            .logout().logoutSuccessUrl("/home/login-page")
            .and()
            .httpBasic().disable();
}

【讨论】:

    【解决方案2】:

    还有一种选择,只需确保检索用户和角色信息的查询根据您的数据库架构进行更改。

    jdbc-身份验证

    <authentication-manager>
          <authentication-provider>
            <jdbc-user-service data-source-ref="dataSource"
              users-by-username-query=
                "select username,password, enabled from users where username=?"
              authorities-by-username-query=
                "select username, role from user_roles where username =?  " />
          </authentication-provider>
        </authentication-manager>
    

    数据源是一个bean

    <bean id="dataSource"
            class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    
            <property name="driverClassName" value="com.mysql.jdbc.Driver" />
            <property name="url" value="jdbc:mysql://localhost:3306/mydb" />
            <property name="username" value="root" />
            <property name="password" value="password" />
        </bean>
    

    这是一个很好的例子:http://www.mkyong.com/spring-security/spring-security-form-login-using-database/

    【讨论】:

      猜你喜欢
      • 2014-04-06
      • 2012-01-23
      • 2015-10-08
      • 2015-08-12
      • 2020-08-06
      • 1970-01-01
      • 1970-01-01
      • 2015-11-19
      • 2017-03-03
      相关资源
      最近更新 更多