https://blog.csdn.net/honghailiang888/article/details/53520557
spring security完全可以作為一個專門的專題來說,有一個專題寫的不錯http://www.iteye.com/blogs/subjects/spring_security,我這里主要是針對4.1.3進行配置說明
一、所需的庫文件
-
//spring-security
-
compile 'org.springframework.security:spring-security-web:4.1.3.RELEASE'
-
compile 'org.springframework.security:spring-security-config:4.1.3.RELEASE'
-
compile 'org.springframework.security:spring-security-taglibs:4.1.3.RELEASE'
二、web配置
從4以后security就只吃java配置了,具體可以看下《spring in action第四版》,我這里還是使用xml配置
過濾器配置,security是基於過濾器的,web.xml
-
<!-- Spring-security -->
-
<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>
需要注意的是,如果配置了sitemesh裝飾器,如果在裝飾器頁面中用到了security,比如標簽,那么security過濾器需要配置在sitemesh之前,否則裝飾器頁中的<sec:authorize>標簽可能不起作用
-
<!-- Spring-security -->
-
<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>
-
-
<!--sitemesh裝飾器放在spring security過來器的后面,以免裝飾器頁中的security不起作用-->
-
<filter>
-
<filter-name>sitemesh</filter-name>
-
<filter-class>
-
org.sitemesh.config.ConfigurableSiteMeshFilter
-
</filter-class>
-
<init-param>
-
<param-name>ignore</param-name>
-
<param-value>true</param-value>
-
</init-param>
-
<init-param>
-
<param-name>encoding</param-name>
-
<param-value>UTF-8</param-value>
-
</init-param>
-
</filter>
-
<filter-mapping>
-
<filter-name>sitemesh</filter-name>
-
<url-pattern>/*</url-pattern>
-
</filter-mapping>
裝飾器頁面中的使用
-
<sec:authorize access="!hasRole('ROLE_USER')">
-
<li>你好,歡迎來到Mango!<a href="<c:url value='/login'/>" class="current">登錄</a></li>
-
</sec:authorize>
-
<sec:authorize access="hasRole('ROLE_USER')">
-
<li><sec:authentication property="principal.username"/>歡迎光臨Mango!<a href="<c:url value='/logout'/>" class="current">退出</a></li>
-
</sec:authorize>
三、security配置文件配置
applicationContext-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" >
-
<form-login
-
login-page="/login"
-
authentication-failure-url="/login?error"
-
login-processing-url="/login"
-
always-use-default-target="false"
-
authentication-success-handler-ref="myAuthenticationSuccessHandler" />
-
<!-- 認證成功用自定義類myAuthenticationSuccessHandler處理 -->
-
-
<logout logout-url="/logout"
-
logout-success-url="/"
-
invalidate-session="true"
-
delete-cookies="JSESSIONID"/>
-
-
<csrf disabled="true" />
-
<intercept-url pattern="/order/*" access="hasRole('ROLE_USER')"/>
-
</http>
-
-
<!-- 使用自定義類myUserDetailsService從數據庫獲取用戶信息 -->
-
<authentication-manager>
-
<authentication-provider user-service-ref="myUserDetailsService">
-
<!-- 加密 -->
-
<password-encoder hash="md5">
-
</password-encoder>
-
</authentication-provider>
-
</authentication-manager>
-
-
</ beans:beans>
這里配置了自定義登錄界面/login,還需要配置控制器條撞到login.jsp頁面,如果字段使用默認值為username和password,當然也可以用 form-login標簽中的屬性username-parameter="username"password-parameter="password"進行設置,這里的值要和登錄頁面中的字段一致。login.jsp
-
<%@ page language="java" pageEncoding="UTF-8" contentType="text/html;charset=UTF-8"%>
-
<%@ include file="../includes/taglibs.jsp"%>
-
-
<html>
-
<head>
-
<title>Mango-Login</title>
-
<meta name="menu" content="home" />
-
</head>
-
-
<body>
-
-
<h1>請登錄!</h1>
-
-
<div style="text-align:center">
-
<form action="<c:url value='/login' />" method="post">
-
<c:if test="${not empty error}">
-
<p style="color:red">${error}</p>
-
</c:if>
-
<table>
-
<tr>
-
<td>用戶名:</td>
-
<td><input type="text" name="username"/></td>
-
</tr>
-
<tr>
-
<td>密碼:</td>
-
<td><input type="password" name="password"/></td>
-
</tr>
-
<tr>
-
<td colspan="2" align="center">
-
<input type="submit" value="登錄"/>
-
<input type="reset" value="重置"/>
-
</td>
-
</tr>
-
</table>
-
</form>
-
</div>
-
-
</body>
-
</html>
其中,form action的值要和配置文件中login-process-url的值一致,提交后UsernamePasswordAuthenticationFilter才能對其進行授權認證。
另外認證是采用的自定義myUserDetailsService獲取用戶信息方式,由於該項目中集成的是Hibernate,所以自己定義了,security系統中是支持jdbc進行獲取的
-
package com.mango.jtt.springSecurity;
-
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.security.core.authority.AuthorityUtils;
-
import org.springframework.security.core.userdetails.User;
-
import org.springframework.security.core.userdetails.UserDetails;
-
import org.springframework.security.core.userdetails.UserDetailsService;
-
import org.springframework.security.core.userdetails.UsernameNotFoundException;
-
import org.springframework.stereotype.Service;
-
-
import com.mango.jtt.po.MangoUser;
-
import com.mango.jtt.service.IUserService;
-
-
/**
-
* 從數據庫中獲取信息的自定義類
-
*
-
* @author HHL
-
*
-
*/
-
-
public class MyUserDetailsService implements UserDetailsService {
-
-
-
private IUserService userService;
-
-
/**
-
* 獲取用戶信息,設置角色
-
*/
-
-
public UserDetails loadUserByUsername(String username)
-
throws UsernameNotFoundException {
-
// 獲取用戶信息
-
MangoUser mangoUser = userService.getUserByName(username);
-
if (mangoUser != null) {
-
// 設置角色
-
return new User(mangoUser.getUserName(), mangoUser.getPassword(),
-
AuthorityUtils.createAuthorityList(mangoUser.getRole()));
-
}
-
-
throw new UsernameNotFoundException("User '" + username
-
+ "' not found.");
-
}
-
-
}
認證成功之后也是自定義了處理類myAuthenticationSuccessHandler,該處理類繼承了SavedRequestAwareAuthenticationSuccessHandler,實現了保存請求信息的操作,如果不配置,默認的也是交給SavedRequestAwareAuthenticationSuccessHandler處理,因為在解析security配置文件時,如果沒有配置會將此設置為默認值。
-
package com.mango.jtt.springSecurity;
-
-
import java.io.IOException;
-
-
import javax.servlet.ServletException;
-
import javax.servlet.http.HttpServletRequest;
-
import javax.servlet.http.HttpServletResponse;
-
-
import org.springframework.beans.factory.annotation.Autowired;
-
import org.springframework.security.core.Authentication;
-
import org.springframework.security.core.userdetails.UserDetails;
-
import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
-
import org.springframework.stereotype.Component;
-
-
import com.mango.jtt.po.MangoUser;
-
import com.mango.jtt.service.IUserService;
-
-
/**
-
* 登錄后操作
-
*
-
* @author HHL
-
* @date
-
*
-
*/
-
-
public class MyAuthenticationSuccessHandler extends
-
SavedRequestAwareAuthenticationSuccessHandler {
-
-
-
private IUserService userService;
-
-
-
public void onAuthenticationSuccess(HttpServletRequest request,
-
HttpServletResponse response, Authentication authentication)
-
throws IOException, ServletException {
-
-
// 認證成功后,獲取用戶信息並添加到session中
-
UserDetails userDetails = (UserDetails) authentication.getPrincipal();
-
MangoUser user = userService.getUserByName(userDetails.getUsername());
-
request.getSession().setAttribute( "user", user);
-
-
super.onAuthenticationSuccess(request, response, authentication);
-
-
}
-
-
-
}
認證失敗則回到登錄頁,只不過多了error,配置為authentication-failure-url="/login?error" 控制類會對其進行處理
-
/**
-
*
-
*/
-
package com.mango.jtt.controller;
-
-
import org.springframework.stereotype.Controller;
-
import org.springframework.ui.Model;
-
import org.springframework.web.bind.annotation.RequestMapping;
-
import org.springframework.web.bind.annotation.RequestParam;
-
-
/**
-
* @author HHL
-
*
-
* @date 2016年12月8日
-
*
-
* 用戶控制類
-
*/
-
-
public class UserController {
-
-
/**
-
* 顯示登錄頁面用,主要是顯示錯誤信息
-
*
-
* @param model
-
* @param error
-
* @return
-
*/
-
-
public String login(Model model,
-
@RequestParam(value = "error", required = false) String error) {
-
if (error != null) {
-
model.addAttribute( "error", "用戶名或密碼錯誤");
-
}
-
return "login";
-
}
-
}
另外,從spring security3.2開始,默認就會啟用csrf保護,本次將csrf保護功能禁用<csrf disabled="true" />,防止頁面中沒有配置crsf而報錯“Could not verify the provided CSRF token because your session was not found.”,如果啟用csrf功能的話需要將login和logout以及上傳功能等都需要進行相應的設置,因此這里先禁用csrf保護功能具體可參考spring-security4.1.3官方文檔
四,后面會對認證過程,以及如何認證的進行詳細說明。
完整代碼:http://download.csdn.net/detail/honghailiang888/9705858
或 https://github.com/honghailiang/SpringMango
Spring安全權限管理(Spring Security)
1.spring Security簡要介紹
Spring Security以前叫做acegi,是后來才成為Spring的一個子項目,也是目前最為流行的一個安全權限管理框架,它與Spring緊密結合在一起。
Spring Security關注的重點是在企業應用安全層為您提供服務,你將發現業務問題領域存在着各式各樣的需求。銀行系統跟電子商務應用就有很大的不同。電子商務系統與企業銷售自動化工具又有很大不同。這些客戶化需求讓應用安全顯得有趣,富有挑戰性而且物有所值。Spring Security為基於J2EE的企業應用軟件提供了一套全面的安全解決方案。
2.為Spring Security配置過濾器和其他參數
要使用Spring Security,首先就是在web.xml中為它配置過濾器, 其次因為我的spring配置文件是放在WEB-INF下的,因此還要配置上下文的參數,最后添加spring的監聽器:
- <?xml version="1.0" encoding="UTF-8"?>
- <web-app version="2.5" xmlns="http://<a href="http://lib.csdn.net/base/17" class='replace_word' title="Java EE知識庫" target='_blank' style='color:#df3434; font-weight:bold;'>Java</a>.sun.com/xml/ns/javaee"
- xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
- xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
- <!-- 配置上下文參數,指定spring配置文件的位置 -->
- <context-param>
- <param-name>contextConfigLocation</param-name>
- <param-value>/WEB-INF/spring-*.xml</param-value>
- </context-param>
- <!-- spring security必須的過濾器,保證在訪問所有的頁面時都必須通過認證 -->
- <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>
- <listener>
- <listener-class>
- org.springframework.web.context.ContextLoaderListener
- </listener-class>
- </listener>
- <welcome-file-list>
- <welcome-file>index.jsp</welcome-file>
- </welcome-file-list>
- <login-config>
- <auth-method>BASIC</auth-method>
- </login-config>
- </web-app>
3.配置security(spring-security.xml)
- <?xml version="1.0" encoding="UTF-8"?>
- <!-- 這里必須使用security的命名空間,提供了beans這個假名 -->
- <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-2.0.xsd
- http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
- <!-- Spring Security采用就近原則,有多個約束時,從上至下只要找到第一條滿足就返回,因此因該將最嚴格的約束放在最前面,而將最寬松的約束放在最后面.auto-config屬性可以讓spring security為我們自動配置幾種常用的權限控制機制,包括form,anonymous, rememberMe等。當然你也可以手工配置。-->
- <http auto-config="true">
- <!-- 我們利用intercept-url來判斷用戶需要具有何種權限才能訪問對應的url資源,可以在pattern中指定一個特定的url資源,也可以使用通配符指定一組類似的url資源。例子中定義的兩個intercepter-url,第一個用來控制對/security/**的訪問,第二個使用了通配符/**,說明它將控制對系統中所有url資源的訪問。 -->
- <intercept-url pattern="/security/**" access="ROLE_ADMIN" />
- <intercept-url pattern="/**" access="ROLE_ADMIN,ROLE_USER" />
- <intercept-url pattern="/login.jsp*" filters="none" />
- <logout logout-url="/logout.jsp"
- logout-success-url="/j_spring_security_check" />
- </http>
- <!-- 使用內存權限管理的配置信息, 在tomcat啟動時,會加載這個文件並一直保存在內存中,知道應用程序重啟,所以也叫內存權限管理
- <authentication-provider>
- <user-service>
- <user name="admin" password="tomcat" authorities="ROLE_ADMIN"/>
- <user name="liky" password="redhat" authorities="ROLE_USER"/>
- </user-service>
- </authentication-provider>
- -->
- <!-- 使用<a href="http://lib.csdn.net/base/14" class='replace_word' title="MySQL知識庫" target='_blank' style='color:#df3434; font-weight:bold;'>數據庫</a>作為權限管理的來源,data-source-ref指定了數據源,所指定的數據源必須包含users, authorities表,並符合security的定義規范 -->
- <authentication-provider>
- <jdbc-user-service data-source-ref="dataSource" />
- </authentication-provider>
- </beans:beans>
4.數據源的配置(spring-common.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-2.5.xsd">
- <!-- 定義數據源 -->
- <bean id="dataSource"
- class="org.apache.commons.dbcp.BasicDataSource">
- <property name="driverClassName"
- value="com.<a href="http://lib.csdn.net/base/14" class='replace_word' title="MySQL知識庫" target='_blank' style='color:#df3434; font-weight:bold;'>MySQL</a>.jdbc.Driver">
- </property>
- <property name="url" value="jdbc:mysql://localhost:3306/csu"></property>
- <property name="username" value="root"></property>
- <property name="password" value="redhat"></property>
- <property name="maxActive" value="100"></property>
- <property name="maxIdle" value="30"></property>
- <property name="maxWait" value="300"></property>
- <property name="defaultAutoCommit" value="true"></property>
- </bean>
- </beans>
5.項目的目錄結構
6. 數據庫腳本
- /-- 注意這里的腳本是MYSQL的,因此在你演示這個實例的時候,要加入MySQL的驅動包 --/
- create table users
- (
- username varchar(50) primary key,
- password varchar(50),
- enabled tinyint(1)
- );
- create table authorities
- (
- id int auto_increment primary key,
- username varchar(50),
- authority varchar(50),
- constraint fk_authorities_users foreign key(username) references users(username)
- );
- create unique index ix_auth_username on authorities (username,authority);
7.部署和配置的要點說明
這是一個Spring Security的數據庫認證實例,要注意以下幾點:
(1)請自行加入Spring必須的包,Spring security的包和MySQL的驅動包,當然你也可以換成其他的數據庫,但是你要相應的修改spring-common.xml中的dataSource部分
(2)數據庫中的兩個表users,authorites必須完全按照腳本所示來定義,也就是說表的名字不能修改.
(3)users表必須包含username,password,enabled字段,這三個字段是絕對不能少的,也不能修改類型.另外enabled一定要為1才能登錄
(4)authorities表必須包含username字段,這個字段引用users的username作為外鍵,authority字段就是角色的名字,角色名字必須滿足ROLE_XXX的格式(例如:ROLE_ADMIN,ROLE_USER,ROLE_MAMAGER)
(5)如果一個用戶有多個角色,不要將多個角色放在一起用逗號隔開.而是每個角色定義一條記錄(例如:abu有ROLE_ADMIN,ROLE_USER兩個角色,那么應該定義兩條記錄: 一條為abu, ROLE_USER,另一條為abu, ROLE_ADMIN.而不是只有一條:abu, ROLE_ADMIN,ROLE_USER)
(6)你可以給authorities表添加一個id字段作為主鍵.