spring security結合數據庫驗證用戶-XML配置方式


之前的用戶信息我們都是使用的內存用戶,測試例子可以,實際中使用肯定不行,需要結合數據庫進行驗證用戶。這就是本節的重點:

項目目錄如下:
 在之前的項目中的依賴中添加兩個依賴:
<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-jdbc</artifactId>
    <version>${spring.version}</version>
</dependency>
<!-- 用於thymeleaf中使用security的標簽 -->
<dependency>
     <groupId>org.thymeleaf.extras</groupId>
     <artifactId>thymeleaf-extras-springsecurity4</artifactId>
     <version>3.0.2.RELEASE</version>
</dependency>
<!-- mysql -->
 <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>${mysql.connector.version}</version>
 </dependency>

spring-jdbc依賴用於數據庫查詢,thymeleaf-extras-springsecurity4是thymeleaf對security標簽的支持

在數據庫中添加兩張表:
CREATE TABLE users (
  username VARCHAR(45) NOT NULL ,
  password VARCHAR(45) NOT NULL ,
  enabled BOOLEAN DEFAULT TRUE NOT NULL,
  PRIMARY KEY (username)
);
CREATE TABLE user_roles (
  user_role_id int(11) NOT NULL AUTO_INCREMENT,
  username varchar(45) NOT NULL,
  role varchar(45) NOT NULL,
  PRIMARY KEY (user_role_id),
  UNIQUE KEY uni_username_role (role,username),
  KEY fk_username_idx (username),
  CONSTRAINT fk_username FOREIGN KEY (username) REFERENCES users (username)
);
INSERT INTO users(username,password,enabled) VALUES ('hxf','123456', true);
INSERT INTO users(username,password,enabled) VALUES ('wpp','123456', true);
INSERT INTO user_roles (username, role) VALUES ('hxf', 'ROLE_USER');
INSERT INTO user_roles (username, role) VALUES ('hxf', 'ROLE_ADMIN');
INSERT INTO user_roles (username, role) VALUES ('wpp', 'ROLE_USER');

這里參考 http://docs.spring.io/spring-security/site/docs/4.2.1.RELEASE/reference/htmlsingle/#user-schema 官網給的配置

一、添加數據庫配置文件spring-database.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"
       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">
    <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/security_learning"/>
        <property name="username" value="petter"/>
        <property name="password" value="petter"/>
    </bean>
</beans>

添加完成以后需要在web.xml文件中指定:

<!-- Loads Spring config file -->
    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            /WEB-INF/spring-security.xml
            /WEB-INF/spring-database.xml
        </param-value>
    </context-param>

二、修改spring-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.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd">
    <!-- use-expressions 允許使用表達式 -->
    <security:http auto-config="true" use-expressions="true">
        <security:intercept-url pattern="/admin**" access="hasRole('ROLE_ADMIN')"/>
        <!-- 拒絕訪問頁面 -->
        <security:access-denied-handler error-page="/403"/>
        <security:form-login
                login-page="/login"
                default-target-url="/welcome"
                authentication-failure-url="/login?error"
                username-parameter="user-name"
                password-parameter="pwd"/>
        <security:logout
                logout-success-url="/login?logout"/>
        <!-- XML 配置中默認csrf是關閉的,此處設置為打開
            如果這里打開csrf,則在form表單中需要添加
            <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
        -->
        <security:csrf />
    </security:http>
    <security:authentication-manager>
        <security:authentication-provider>
            <security: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 = ?"/>
        </security:authentication-provider>
    </security:authentication-manager>
</beans>

三、修改登錄以后默認進入的頁面hello.html

<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml"
      xmlns:th="http://www.thymeleaf.org"
      xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
<head>
    <meta charset="UTF-8" />
    <title>hello</title>
</head>
<body>
    <h1 th:text="|標題: ${title}|">Title : XXX</h1>
    <h1 th:text="|信息: ${message}|">Message : XXX</h1>
    <div sec:authentication="name">
        驗證用戶的名稱顯示在這里
    </div>
    <div sec:authentication="principal.authorities">
        驗證用戶的權限顯示在這里
    </div>
    <!-- 下面注釋掉的兩種寫法是等價的,但是不起作用,暫時使用第三種方式 -->
    <!--<div sec:authorize="hasRole('ROLE_USER')">-->
    <!--<div sec:authorize="hasAuthority('ROLE_USER')">-->
    <div th:if="${#strings.contains(#authentication.principal.authorities,'ROLE_USER')}">
        <form action="/logout" method="post" id="logoutForm">
            <input type="hidden" th:name="${_csrf.parameterName}" th:value="${_csrf.token}" />
        </form>
        <h2><a href="javascript:formSubmit()">退出</a></h2>
        <script>
            function formSubmit() {
                document.getElementById("logoutForm").submit();
            }
        </script>
    </div>
</body>
</html>

這里需要注意:

1、由於采用的是thymeleaf模板,所有不能使用spring security的標簽庫,需要使用thymeleaf擴展的庫,即pom文件中添加的依賴 thymeleaf-extras-springsecurity4
2、在mvc-dispather-servlet.xml文件修改配置把庫加入:
<bean id="templateEngine" class="org.thymeleaf.spring4.SpringTemplateEngine">
        <property name="templateResolver" ref="templateResolver"/>
        <property name="additionalDialects">
            <set>
                <!-- Note the package would change to 'springsecurity3' if you are using that version -->
                <bean class="org.thymeleaf.extras.springsecurity4.dialect.SpringSecurityDialect"/>
            </set>
        </property>
    </bean>

3、如上注釋所示,兩種寫法判斷只用含有USER角色的用戶會顯示,不起作用,可能只會會修復。

PS:要想起作用,thymeleaf-spring4 版本必須是 3.0.3.RELEASE以上

記住,role就是一種約定的前面加上ROLE_作為前綴的特殊的authority,所以它們是等價的,具體可以參考http://stackoverflow.com/questions/19525380/difference-between-role-and-grantedauthority-in-spring-security 

四、添加403.html頁面
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
    <meta charset="UTF-8"/>
    <title>403</title>
</head>
<body>
<h1>HTTP Status 403 - Access is denied</h1>
<div>
    <h2 th:if="username eq null" th:text="您沒有權限訪問這個頁面"></h2>
    <h2 th:if="username ne null" th:text="|用戶:${username},您沒有權限訪問這個頁面|"></h2>
</div>
</body>
</html>

並且在HelloController中添加代碼:

@RequestMapping(value = "/403", method = RequestMethod.GET)
    public ModelAndView accessDenied() {
        ModelAndView model = new ModelAndView();
        //檢查用戶是否已經登錄
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (!(auth instanceof AnonymousAuthenticationToken)) {
            UserDetails userDetail = (UserDetails) auth.getPrincipal();
            model.addObject("username", userDetail.getUsername());
        }
        model.setViewName("403");
        return model;
    }

啟動程序,訪問http://localhost:8080/login http://localhost:8080/admin 登錄不同角色的用戶進行自行測試

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM