如何使用Hibernate和XML配置Spring Security

时间:2017-08-22 21:34:05

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

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

我有一个具有id,username,password,role attributes的实体类(Administrators)(我现在不想使用第二个表'roles')。

我已经阅读了很多教程,其他人建议实体类应该实现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>

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

2 个答案:

答案 0 :(得分:0)

有一种替代方法,只需确保根据您的数据库架构更改检索用户和角色信息的查询。

JDBC-authetnication

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

答案 1 :(得分:0)

首先,您不需要在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()方法来保护Web应用程序的特定页面:

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();
}