在前面三個博客的例子中,登陸頁面都是用的Spring Security自己提供的,這明顯不符合實際開發場景,同時也沒有退出和注銷按鈕,因此在每次測試的時候都要通過關閉瀏覽器來注銷達到清除session的效果。
一 自定義頁面
<%@ page language="java" contentType="text/html; charset=utf-8" pageEncoding="utf-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <title>自定義登陸頁面</title> </head> <body> <div class="error ${param.error == true ? '' : 'hide'}"> 登陸失敗<br> ${sessionScope['SPRING_SECURITY_LAST_EXCEPTION'].message} </div> <form method="post" action="${pageContext.request.contextPath}/j_spring_security_check" style="width:260px; text-align: center"> <fieldset> <legend>登陸</legend> 用戶: <input type="text" name="j_username" style="width: 150px;" value="${sessionScope['SPRING_SECURITY_LAST_USERNAME']}" /><br /> 密碼: <input type="password" name="j_password" style="width: 150px;" /><br /> <input type="checkbox" name="_spring_security_remember_me" />兩周之內不必登陸<br /> <input type="submit" value="登陸" /> <input type="reset" value="重置" /> </fieldset> </form> </body> </html>
說明:
1、特別要注意的是form表單的action是提交登陸信息的地址,這是security內部定義好的,同時自定義form時,要把form的action設置為/j_spring_security_check。注意這里要使用絕對路徑,避免登陸頁面存放的頁面可能帶來的問題。
2、j_username,輸入登陸名的參數名稱,j_password,輸入密碼的參數名稱,這兩個正常情況下也不會修改。
3、_spring_security_remember_me,選擇是否允許自動登錄的參數名稱。可以直接把這個參數設置為一個checkbox,無需設置value,Spring Security會自行判斷它是否被選中,這也是security內部提供的,只需要配置,不需要自己實現。
二 配置制定的頁面
<?xml version="1.0" encoding="UTF-8"?> <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-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security.xsd"> <!-- <http pattern="/login.jsp" security="none"></http> --> <http auto-config="false"> <intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" /> <intercept-url pattern="/adminPage.jsp" access="ROLE_ADMIN" /> <intercept-url pattern="/**" access="ROLE_USER" /> <form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=true" /> <logout invalidate-session="true" logout-success-url="/login.jsp" logout-url="/j_spring_security_logout"/> </http> <!-- 數據源 --> <beans:bean id="dataSource" class="com.mchange.v2.c3p0.ComboPooledDataSource" destroy-method="close"> <!-- 此為c3p0在spring中直接配置datasource c3p0是一個開源的JDBC連接池 --> <beans:property name="driverClass" value="com.mysql.jdbc.Driver" /> <beans:property name="jdbcUrl" value="jdbc:mysql://localhost:3306/springsecuritydemo?useUnicode=true&characterEncoding=UTF-8" /> <beans:property name="user" value="root" /> <beans:property name="password" value="" /> <beans:property name="maxPoolSize" value="50"></beans:property> <beans:property name="minPoolSize" value="10"></beans:property> <beans:property name="initialPoolSize" value="10"></beans:property> <beans:property name="maxIdleTime" value="25000"></beans:property> <beans:property name="acquireIncrement" value="1"></beans:property> <beans:property name="acquireRetryAttempts" value="30"></beans:property> <beans:property name="acquireRetryDelay" value="1000"></beans:property> <beans:property name="testConnectionOnCheckin" value="true"></beans:property> <beans:property name="idleConnectionTestPeriod" value="18000"></beans:property> <beans:property name="checkoutTimeout" value="5000"></beans:property> <beans:property name="automaticTestTable" value="t_c3p0"></beans:property> </beans:bean> <authentication-manager> <authentication-provider> <jdbc-user-service data-source-ref="dataSource" users-by-username-query="select username,password,status as enabled from user where username = ?" authorities-by-username-query="select user.username,role.name from user,role,user_role where user.id=user_role.user_id and user_role.role_id=role.id and user.username=?"/> </authentication-provider> </authentication-manager> </beans:beans>
說明:
1、form-login這個標簽是配置登陸頁面的,其中的屬性login-page是配置登陸頁面的,default-target-url配置登陸成功后跳轉到的頁面,authentication-failure-url配置認證失敗后的跳轉頁面。
2、在上面的配置中,登陸頁面肯定是不能攔截的,任何人都應該可以訪問,<intercept-url pattern="/login.jsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />配置表示允許匿名用戶訪問,就是不用身份都可以訪問;還有另一種配置方式:<http pattern="/login.jsp" security="none"></http>,這種配置達到的目的都是一樣的。
3、logout這個標簽用來配置退出或者注銷,其中的屬性invalidate-session,配置否是要清除session,logout-success-url配置注銷成功后的跳轉頁面,logout-url提交退出或者注銷的地址,因此我們在配置退出或者注銷的時候,只需要將url設置為/j_spring_security_logout即可,這個地址也是security內部實現了的。
4、form-login標簽中還有一個特別要注意的屬性use-expressions,如果設置為true,這配置access就要做相應的改變,否則項目啟動的時候會報錯,錯誤如下:
如果use-expressns="true"時,則表示改為 SpEL 表達式。 SpEL 允許使用特定的訪問控制規則表達式語言。與簡單的字符串如 ROLE_USER 不同,配置文件可以指明表達式語言觸發方法調用、引用系統屬性、計算機值等等。http標簽中的配置改為如下:
<http auto-config="false" use-expressions="true"> <intercept-url pattern="/login.jsp" access="permitAll" /> <intercept-url pattern="/adminPage.jsp" access="hasRole('ROLE_ADMIN')" /> <intercept-url pattern="/**" access="hasRole('ROLE_USER')" /> <form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=true" /> <logout invalidate-session="true" logout-success-url="/login.jsp" logout-url="/j_spring_security_logout"/> </http>
配置文件中的其他配置在前面幾篇博客中都有詳細的講解,這里就不贅述了。
三 其他文件
index.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h1>this is a user page</h1> <a href="${pageContext.request.contextPath}/j_spring_security_logout">退出登陸</a> </body> </html>
adminPage.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <title>Insert title here</title> </head> <body> <h1>this is a admin page</h1> <a href="${pageContext.request.contextPath}/j_spring_security_logout">退出登陸</a> </body> </html>
這里定義了兩個頁面,index.jsp用戶和管理員都可以訪問,adminPage.jsp只有管理員可以訪問,同時兩個頁面都有注銷按鈕,注銷按鈕提交的地址也就是上面配置文件中的地址/j_spring_security_logout。
pom.xml和前面的一樣,這里就不貼了。
四 結果
當輸入普通用戶的用戶名和密碼,同時勾選2周不用登陸后,因為adminPage.jsp頁面要有管理員權限才能訪問,所以普通用戶訪問失敗,index.jsp頁面就可以訪問;這時關閉頁面后,再次訪問資源,因為勾選了2周不用登陸,所以可以成功訪問;但是當點擊退出登錄后,再次訪問是就會跳轉到登陸頁面,要求登陸才能訪問。
當輸入管理員名和密碼,同時勾選2周不用登陸,驗證成功后,跳轉到index.jsp,同時adminPage.jsp也可以訪問,這時把一個頁面關閉再重新訪問資源時,因為勾選2周不用登陸,所以可以成功訪問;然后注銷,這是再訪問資源時,就會跳轉到登陸頁面,要求登陸才能訪問。
---------------------
作者:AirMario
來源:CSDN
原文:https://blog.csdn.net/AirMario/article/details/54022812