日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

Spring boot+Spring Security 4配置整合实例

發布時間:2024/4/14 javascript 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Spring boot+Spring Security 4配置整合实例 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

本例所覆蓋的內容:

1.?使用Spring Security管理用戶身份認證、登錄退出

2.?用戶密碼加密及驗證

3.?采用數據庫的方式實現Spring Securityremember-me功能

4.?獲取登錄用戶信息。

5.使用Spring Security管理url和權限

?

本例所使用的框架:

1.?Spring boot

2.?Spring MVC

3.?Spring Security

4.?Spring Data JPA

5.?thymeleaf

6.gradle

一、?整合Spring Security

build.gradle中加入如下片段:

[plain] view plaincopyprint?
  • ??
  • [plain] view plain copy print?
  • compile('org.springframework.boot:spring-boot-starter-data-jpa')??
  • compile("org.springframework.boot:spring-boot-starter-thymeleaf")??
  • compile("org.springframework.boot:spring-boot-starter-security")<u>??
  • ????testCompile("org.springframework.boot:spring-boot-starter-test")??
  • testCompile("org.springframework.security:spring-security-test")??
  • compile('org.springframework.boot:spring-boot-starter-data-jpa')compile("org.springframework.boot:spring-boot-starter-thymeleaf")compile("org.springframework.boot:spring-boot-starter-security") testCompile("org.springframework.boot:spring-boot-starter-test")testCompile("org.springframework.security:spring-security-test")

    使用Spring Security4的四種方法概述

    ????那么在Spring Security4的使用中,有4種方法:

  • ? ? 一種是全部利用配置文件,將用戶、權限、資源(url)硬編碼在xml文件中;
  • ? ? 二種是用戶和權限用數據庫存儲,而資源(url)和權限的對應采用硬編碼配置。
  • ? ? 三種是細分角色和權限,并將用戶、角色、權限和資源均采用數據庫存儲,并且自定義過濾器,代替原有的FilterSecurityInterceptor過濾器 ? ? ? ? 并分別實現AccessDecisionManager、InvocationSecurityMetadataSourceService和UserDetailsService,并在配置文件中進行相應配置。
  • ? ? 四是修改spring security的源代碼,主要是修改InvocationSecurityMetadataSourceService和UserDetailsService兩個類。 前者是將配置文件 ? ? 或數據庫中存儲的資源(url)提取出來加工成為url和權限列表的Map供Security使用,后者提取用戶名和權限組成一個完整的(UserDetails)User ? ? 對象,該對象可以提供用戶的詳細信息供AuthentationManager進行認證與授權使用。
  • 我們今天來實現一下第三種。

    ?當然,spring security4畢竟是西方國家的東西,以英文為主,使用習慣和文化的差異共存,況且為了適應大多數Web應用的權限管理,作者將Spring Security4打造的精簡而靈活。精簡指Spring Security4對用戶和權限的表設計的非常簡單,并且沒有采用數據庫來管理資源(URL)。這樣的話,對于我們國人用戶來說,是個很大的遺憾,這個遺憾甚至能夠影響到我們對安全框架的選型。你想啊,在國內大多數項目中,均設置了比較復雜的權限控制,一般就會涉及到用戶、角色、資源3張表,若要加上3張表之間的對應關系表2張,得有5張表。

    ? ? 但是,Spring Security4提供了靈活的擴展方法。具體應該擴展哪些類呢? 或者到底Spring Security3工作的流程如何,你不妨參看下面一篇文章,就會獲得
    一些啟示,網址為:http://www.blogjava.net/SpartaYew/archive/2011/06/15/350630.html, 哈哈,謝謝分享。

    還有一個地址很有價值,http://download.csdn.net/detail/muddled/8981809,我就參考著上面的介紹擴展了4個類。

    首先來說一下第三種方法的實現流程,我畫了一張簡易版流程圖,幫助大家理解spring security4 的工作機制:


    下面我們就來根據這個圖中標注出的,重要的幾個4個類來配置吧!

  • 當然要現在application.properties配置文件中配置好數據庫。
  • 開始配置相關的實體類 SysUser.java ?SRole.java ?SysResource.java?SysResourceRole.java
  • [java] view plaincopyprint?
  • package?security.entity;??
  • ??
  • import?java.util.Date;??
  • import?java.util.HashSet;??
  • import?java.util.Set;??
  • ??
  • import?javax.persistence.Column;??
  • import?javax.persistence.Entity;??
  • import?javax.persistence.FetchType;??
  • import?javax.persistence.GeneratedValue;??
  • import?javax.persistence.GenerationType;??
  • import?javax.persistence.Id;??
  • import?javax.persistence.OneToMany;??
  • import?javax.persistence.Table;??
  • import?javax.persistence.Temporal;??
  • import?javax.persistence.TemporalType;??
  • ????@Entity??
  • ????@Table(name?=?"s_user")//code11??
  • ????public?class?SysUser?implements?java.io.Serializable?{??
  • ??????????
  • ????????@Id??
  • ????????@GeneratedValue(strategy?=?GenerationType.IDENTITY)??
  • ????????@Column(name?=?"id",?unique?=?true,?nullable?=?false)??
  • ????????private?Integer?id;??
  • ????????@Column(name?=?"name",?length?=?120)??
  • ????????private?String?name;?//用戶名??
  • ????????@Column(name?=?"email",?length?=?50)??
  • ????????private?String?email;//用戶郵箱??
  • ????????@Column(name?=?"password",?length?=?120)??
  • ????????private?String?password;//用戶密碼??
  • ????????@Temporal(TemporalType.DATE)??
  • ????????@Column(name?=?"dob",?length?=?10)??
  • ????????private?Date?dob;//時間??
  • ??????????
  • ????????@OneToMany(fetch?=?FetchType.EAGER,?mappedBy?=?"SUser")??
  • ????????private?Set<SysRole>?SysRoles?=?new?HashSet<SysRole>(0);//?所對應的角色集合??
  • ??
  • ????????public?SysUser()?{??
  • ????????}??
  • ??
  • ????????public?SysUser(String?name,?String?email,?String?password,?Date?dob,?Set<SysRole>?SysRoles)?{??
  • ????????????this.name?=?name;??
  • ????????????this.email?=?email;??
  • ????????????this.password?=?password;??
  • ????????????this.dob?=?dob;??
  • ????????????this.SysRoles?=?SysRoles;??
  • ????????}??
  • ??
  • ??????????
  • ????????public?Integer?getId()?{??
  • ????????????return?this.id;??
  • ????????}??
  • ??
  • ????????public?void?setId(Integer?id)?{??
  • ????????????this.id?=?id;??
  • ????????}??
  • ??
  • ??????????
  • ????????public?String?getName()?{??
  • ????????????return?this.name;??
  • ????????}??
  • ??
  • ????????public?void?setName(String?name)?{??
  • ????????????this.name?=?name;??
  • ????????}??
  • ??
  • ????????public?String?getEmail()?{??
  • ????????????return?this.email;??
  • ????????}??
  • ??
  • ????????public?void?setEmail(String?email)?{??
  • ????????????this.email?=?email;??
  • ????????}??
  • ??
  • ????????public?String?getPassword()?{??
  • ????????????return?this.password;??
  • ????????}??
  • ??
  • ????????public?void?setPassword(String?password)?{??
  • ????????????this.password?=?password;??
  • ????????}??
  • ??
  • ??????????
  • ????????public?Date?getDob()?{??
  • ????????????return?this.dob;??
  • ????????}??
  • ??
  • ????????public?void?setDob(Date?dob)?{??
  • ????????????this.dob?=?dob;??
  • ????????}??
  • ??
  • ????????@OneToMany(fetch?=?FetchType.EAGER,?mappedBy?=?"SUser")??
  • ????????public?Set<SysRole>?getSysRoles()?{??
  • ????????????return?this.SysRoles;??
  • ????????}??
  • ??
  • ????????public?void?setSRoles(Set<SysRole>?SysRoles)?{??
  • ????????????this.SysRoles?=?SysRoles;??
  • ????????}??
  • ??
  • }??
  • package security.entity;import java.util.Date; import java.util.HashSet; import java.util.Set;import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.OneToMany; import javax.persistence.Table; import javax.persistence.Temporal; import javax.persistence.TemporalType;@Entity@Table(name = "s_user")//code11public class SysUser implements java.io.Serializable {@Id@GeneratedValue(strategy = GenerationType.IDENTITY)@Column(name = "id", unique = true, nullable = false)private Integer id;@Column(name = "name", length = 120)private String name; //用戶名@Column(name = "email", length = 50)private String email;//用戶郵箱@Column(name = "password", length = 120)private String password;//用戶密碼@Temporal(TemporalType.DATE)@Column(name = "dob", length = 10)private Date dob;//時間@OneToMany(fetch = FetchType.EAGER, mappedBy = "SUser")private Set<SysRole> SysRoles = new HashSet<SysRole>(0);// 所對應的角色集合public SysUser() {}public SysUser(String name, String email, String password, Date dob, Set<SysRole> SysRoles) {this.name = name;this.email = email;this.password = password;this.dob = dob;this.SysRoles = SysRoles;}public Integer getId() {return this.id;}public void setId(Integer id) {this.id = id;}public String getName() {return this.name;}public void setName(String name) {this.name = name;}public String getEmail() {return this.email;}public void setEmail(String email) {this.email = email;}public String getPassword() {return this.password;}public void setPassword(String password) {this.password = password;}public Date getDob() {return this.dob;}public void setDob(Date dob) {this.dob = dob;}@OneToMany(fetch = FetchType.EAGER, mappedBy = "SUser")public Set<SysRole> getSysRoles() {return this.SysRoles;}public void setSRoles(Set<SysRole> SysRoles) {this.SysRoles = SysRoles;}}
    [java] view plaincopyprint?
  • package?security.entity;??
  • ??
  • import?java.util.Date;??
  • ??
  • import?javax.persistence.Column;??
  • import?javax.persistence.Entity;??
  • import?javax.persistence.FetchType;??
  • import?javax.persistence.GeneratedValue;??
  • import?javax.persistence.GenerationType;??
  • import?javax.persistence.Id;??
  • import?javax.persistence.JoinColumn;??
  • import?javax.persistence.ManyToOne;??
  • import?javax.persistence.Table;??
  • //角色表??
  • @Entity??
  • @Table(name="s_role")??
  • public?class?SysRole?{??
  • ????@Id??
  • ????@GeneratedValue(strategy=GenerationType.IDENTITY)??
  • ????@Column?(name="id",length=10)??
  • ????private?int?id;??
  • ??????
  • ????@ManyToOne(fetch?=?FetchType.LAZY)??
  • ????@JoinColumn(name?=?"uid",?nullable?=?false)??
  • ????private?SysUser?SUser;//角色對應的用戶實體??
  • ??????
  • ????@Column(name="name",length=100)??
  • ????private?String?name;//角色名稱??
  • ??????
  • ????public?int?getId()?{??
  • ????????return?id;??
  • ????}??
  • ????public?void?setId(int?id)?{??
  • ????????this.id?=?id;??
  • ????}??
  • ??????
  • ????public?String?getName()?{??
  • ????????return?name;??
  • ????}??
  • ????public?void?setName(String?name)?{??
  • ????????this.name?=?name;??
  • ????}??
  • ????public?SysUser?getSUser()?{??
  • ????????return?SUser;??
  • ????}??
  • ????public?void?setSUser(SysUser?sUser)?{??
  • ????????SUser?=?sUser;??
  • ????}??
  • ??????
  • ??????
  • }??
  • package security.entity;import java.util.Date;import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; //角色表 @Entity @Table(name="s_role") public class SysRole {@Id@GeneratedValue(strategy=GenerationType.IDENTITY)@Column (name="id",length=10)private int id;@ManyToOne(fetch = FetchType.LAZY)@JoinColumn(name = "uid", nullable = false)private SysUser SUser;//角色對應的用戶實體@Column(name="name",length=100)private String name;//角色名稱public int getId() {return id;}public void setId(int id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}public SysUser getSUser() {return SUser;}public void setSUser(SysUser sUser) {SUser = sUser;}}
    [java] view plaincopyprint?
  • package?cn.paybay.ticketManager.entity;??
  • ??
  • import?javax.persistence.Column;??
  • import?javax.persistence.Entity;??
  • import?javax.persistence.GeneratedValue;??
  • import?javax.persistence.GenerationType;??
  • import?javax.persistence.Id;??
  • import?javax.persistence.Table;??
  • @Entity??
  • @Table(name="s_resource")??
  • public?class?SysResource?{??
  • ????????@Id??
  • ????????@GeneratedValue(strategy=GenerationType.IDENTITY)??
  • ????????@Column?(name="id",length=10)??
  • ????????private?int?id;??
  • ??????????
  • ????????@Column(name="resourceString",length=1000)??
  • ????????private?String?resourceString;//url??
  • ??????????
  • ????????@Column(name="resourceId",length=50)??
  • ????????private?String?resourceId;//資源ID??
  • ??????????
  • ????????@Column(name="remark",length=200)??
  • ????????private?String?remark;//備注??
  • ??????????
  • ????????@Column(name="resourceName",length=400)??
  • ????????private?String?resourceName;//資源名稱??
  • ??????????
  • ????????@Column(name="methodName",length=400)??
  • ????????private?String?methodName;//資源所對應的方法名??
  • ??????????
  • ????????@Column(name="methodPath",length=1000)??
  • ????????private?String?methodPath;//資源所對應的包路徑??
  • ??????????
  • ????????public?int?getId()?{??
  • ????????????return?id;??
  • ????????}??
  • ??
  • ????????public?void?setId(int?id)?{??
  • ????????????this.id?=?id;??
  • ????????}??
  • ??
  • ????????public?String?getResourceString()?{??
  • ????????????return?resourceString;??
  • ????????}??
  • ??
  • ????????public?void?setResourceString(String?resourceString)?{??
  • ????????????this.resourceString?=?resourceString;??
  • ????????}??
  • ??
  • ????????public?String?getResourceId()?{??
  • ????????????return?resourceId;??
  • ????????}??
  • ??
  • ????????public?void?setResourceId(String?resourceId)?{??
  • ????????????this.resourceId?=?resourceId;??
  • ????????}??
  • ??
  • ????????public?String?getRemark()?{??
  • ????????????return?remark;??
  • ????????}??
  • ??
  • ????????public?void?setRemark(String?remark)?{??
  • ????????????this.remark?=?remark;??
  • ????????}??
  • ??
  • ????????public?String?getResourceName()?{??
  • ????????????return?resourceName;??
  • ????????}??
  • ??
  • ????????public?void?setResourceName(String?resourceName)?{??
  • ????????????this.resourceName?=?resourceName;??
  • ????????}??
  • ??
  • ????????public?String?getMethodName()?{??
  • ????????????return?methodName;??
  • ????????}??
  • ??
  • ????????public?void?setMethodName(String?methodName)?{??
  • ????????????this.methodName?=?methodName;??
  • ????????}??
  • ??
  • ????????public?String?getMethodPath()?{??
  • ????????????return?methodPath;??
  • ????????}??
  • ??
  • ????????public?void?setMethodPath(String?methodPath)?{??
  • ????????????this.methodPath?=?methodPath;??
  • ????????}??
  • ??????????
  • ??????????
  • }??
  • package cn.paybay.ticketManager.entity;import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name="s_resource") public class SysResource {@Id@GeneratedValue(strategy=GenerationType.IDENTITY)@Column (name="id",length=10)private int id;@Column(name="resourceString",length=1000)private String resourceString;//url@Column(name="resourceId",length=50)private String resourceId;//資源ID@Column(name="remark",length=200)private String remark;//備注@Column(name="resourceName",length=400)private String resourceName;//資源名稱@Column(name="methodName",length=400)private String methodName;//資源所對應的方法名@Column(name="methodPath",length=1000)private String methodPath;//資源所對應的包路徑public int getId() {return id;}public void setId(int id) {this.id = id;}public String getResourceString() {return resourceString;}public void setResourceString(String resourceString) {this.resourceString = resourceString;}public String getResourceId() {return resourceId;}public void setResourceId(String resourceId) {this.resourceId = resourceId;}public String getRemark() {return remark;}public void setRemark(String remark) {this.remark = remark;}public String getResourceName() {return resourceName;}public void setResourceName(String resourceName) {this.resourceName = resourceName;}public String getMethodName() {return methodName;}public void setMethodName(String methodName) {this.methodName = methodName;}public String getMethodPath() {return methodPath;}public void setMethodPath(String methodPath) {this.methodPath = methodPath;}}
    [java] view plaincopyprint?
  • package?security.entity;??
  • ??
  • import?java.util.Date;??
  • ??
  • import?javax.persistence.Column;??
  • import?javax.persistence.Entity;??
  • import?javax.persistence.FetchType;??
  • import?javax.persistence.GeneratedValue;??
  • import?javax.persistence.GenerationType;??
  • import?javax.persistence.Id;??
  • import?javax.persistence.JoinColumn;??
  • import?javax.persistence.ManyToOne;??
  • import?javax.persistence.Table;??
  • @Entity??
  • @Table(name="s_resource_role")??
  • public?class?SysResourceRole?{??
  • ????????@Id??
  • ????????@GeneratedValue(strategy=GenerationType.IDENTITY)??
  • ????????@Column?(name="id",length=10)??
  • ????????private?int?id;??
  • ??????????
  • ????????@Column(name="roleId",length=50)??
  • ????????private?String?roleId;?//角色ID??
  • ??????????
  • ????????@Column(name="resourceId",length=50)??
  • ????????private?String?resourceId;//資源ID??
  • ??????????
  • ????????@Column(name="updateTime")??
  • ????????private?Date?updateTime;//更新時間??
  • ??
  • ????????public?int?getId()?{??
  • ????????????return?id;??
  • ????????}??
  • ??
  • ????????public?void?setId(int?id)?{??
  • ????????????this.id?=?id;??
  • ????????}??
  • ??
  • ????????public?String?getRoleId()?{??
  • ????????????return?roleId;??
  • ????????}??
  • ??
  • ????????public?void?setRoleId(String?roleId)?{??
  • ????????????this.roleId?=?roleId;??
  • ????????}??
  • ??
  • ????????public?String?getResourceId()?{??
  • ????????????return?resourceId;??
  • ????????}??
  • ??
  • ????????public?void?setResourceId(String?resourceId)?{??
  • ????????????this.resourceId?=?resourceId;??
  • ????????}??
  • ??
  • ????????public?Date?getUpdateTime()?{??
  • ????????????return?updateTime;??
  • ????????}??
  • ??
  • ????????public?void?setUpdateTime(Date?updateTime)?{??
  • ????????????this.updateTime?=?updateTime;??
  • ????????}??
  • ??
  • ??????????
  • }??
  • package security.entity;import java.util.Date;import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.FetchType; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.JoinColumn; import javax.persistence.ManyToOne; import javax.persistence.Table; @Entity @Table(name="s_resource_role") public class SysResourceRole {@Id@GeneratedValue(strategy=GenerationType.IDENTITY)@Column (name="id",length=10)private int id;@Column(name="roleId",length=50)private String roleId; //角色ID@Column(name="resourceId",length=50)private String resourceId;//資源ID@Column(name="updateTime")private Date updateTime;//更新時間public int getId() {return id;}public void setId(int id) {this.id = id;}public String getRoleId() {return roleId;}public void setRoleId(String roleId) {this.roleId = roleId;}public String getResourceId() {return resourceId;}public void setResourceId(String resourceId) {this.resourceId = resourceId;}public Date getUpdateTime() {return updateTime;}public void setUpdateTime(Date updateTime) {this.updateTime = updateTime;}}
    好了實體類都建好了。然后運行一下,springboot程序。hibernate會自動創建表。在表中插入幾條測試數據:
  • s_user表
  • s_role表

  • ? ? ?6.s_resource表


    ? ? ? 7.s_resource_role表


    [sql] view plaincopyprint?
  • <span?style="color:rgb(51,204,0);">//請勿手工寫入數據?供remember-me功能使用</span>??
  • CREATE?TABLE?`persistent_logins`?(??
  • ??`username`?varchar(64)?NOT?NULL,??
  • ??`series`?varchar(64)?NOT?NULL,??
  • ??`token`?varchar(64)?NOT?NULL,??
  • ??`last_used`?timestamp?NOT?NULL?DEFAULT?CURRENT_TIMESTAMP?ON?UPDATE?CURRENT_TIMESTAMP,??
  • ??PRIMARY?KEY?(`series`)??
  • )??
  • //請勿手工寫入數據 供remember-me功能使用 CREATE TABLE `persistent_logins` (`username` varchar(64) NOT NULL,`series` varchar(64) NOT NULL,`token` varchar(64) NOT NULL,`last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,PRIMARY KEY (`series`) )

    好了,現在我們來配置一下用戶和角色的認證吧。

    1、首先,創建WebSecurityConfig.java配置類,其中不明所以的地方請參照上面的圖,慢慢往下看。

    [java] view plaincopyprint?
  • package?security;??
  • ??
  • import?org.springframework.beans.factory.annotation.Autowired;??
  • import?org.springframework.context.annotation.Bean;??
  • import?org.springframework.context.annotation.Configuration;??
  • import?org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;??
  • import?org.springframework.security.config.annotation.web.builders.HttpSecurity;??
  • import?org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;??
  • import?org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;??
  • import?org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;??
  • import?org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;??
  • ??
  • import?security.support.CustomUserDetailsService;??
  • import?security.support.LoginSuccessHandler;??
  • @Configuration??
  • @EnableWebSecurity??
  • public?class?WebSecurityConfig?extends?WebSecurityConfigurerAdapter?{??
  • ????@Autowired??
  • ????private?CustomUserDetailsService?customUserDetailsService;??
  • ????//http://localhost:8080/login?輸入正確的用戶名密碼?并且選中remember-me?則登陸成功,轉到?index頁面???
  • ????//再次訪問index頁面無需登錄直接訪問??
  • ????//訪問http://localhost:8080/home?不攔截,直接訪問,??
  • ????//訪問http://localhost:8080/hello?需要登錄驗證后,且具備?“ADMIN”權限hasAuthority("ADMIN")才可以訪問??
  • ????@Override??
  • ????protected?void?configure(HttpSecurity?http)?throws?Exception?{??
  • ????????http??
  • ????????.authorizeRequests()??
  • ????????.antMatchers("/home").permitAll()//訪問:/home?無需登錄認證權限??
  • ????????.anyRequest().authenticated()?//其他所有資源都需要認證,登陸后訪問??
  • ????????.antMatchers("/hello").hasAuthority("ADMIN")?//登陸后之后擁有“ADMIN”權限才可以訪問/hello方法,否則系統會出現“403”權限不足的提示??
  • ????????.and()??
  • ????????.formLogin()??
  • ????????.loginPage("/login")//指定登錄頁是”/login”??
  • ????????.permitAll()??
  • ????????.successHandler(loginSuccessHandler())?//登錄成功后可使用loginSuccessHandler()存儲用戶信息,可選。??
  • ????????.and()??
  • ????????.logout()??
  • ????????.logoutSuccessUrl("/home")?//退出登錄后的默認網址是”/home”??
  • ????????.permitAll()??
  • ????????.invalidateHttpSession(true)??
  • ????????.and()??
  • ????????.rememberMe()//登錄后記住用戶,下次自動登錄,數據庫中必須存在名為persistent_logins的表??
  • ????????.tokenValiditySeconds(1209600);??
  • ????}??
  • ??
  • ????@Autowired??
  • ????public?void?configureGlobal(AuthenticationManagerBuilder?auth)?throws?Exception?{?????
  • //指定密碼加密所使用的加密器為passwordEncoder()??
  • //需要將密碼加密后寫入數據庫???
  • ????auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());??
  • ????????auth.eraseCredentials(false);?????????
  • ????}??
  • ??
  • ????@Bean??
  • ????public?BCryptPasswordEncoder?passwordEncoder()?{??
  • ????????return?new?BCryptPasswordEncoder(4);??
  • ????}??
  • ??
  • ????@Bean??
  • ????public?LoginSuccessHandler?loginSuccessHandler(){??
  • ????????return?new?LoginSuccessHandler();??
  • ????}??
  • }??
  • package security;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;import security.support.CustomUserDetailsService; import security.support.LoginSuccessHandler; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate CustomUserDetailsService customUserDetailsService;//http://localhost:8080/login 輸入正確的用戶名密碼 并且選中remember-me 則登陸成功,轉到 index頁面 //再次訪問index頁面無需登錄直接訪問//訪問http://localhost:8080/home 不攔截,直接訪問,//訪問http://localhost:8080/hello 需要登錄驗證后,且具備 “ADMIN”權限hasAuthority("ADMIN")才可以訪問@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().antMatchers("/home").permitAll()//訪問:/home 無需登錄認證權限.anyRequest().authenticated() //其他所有資源都需要認證,登陸后訪問.antMatchers("/hello").hasAuthority("ADMIN") //登陸后之后擁有“ADMIN”權限才可以訪問/hello方法,否則系統會出現“403”權限不足的提示.and().formLogin().loginPage("/login")//指定登錄頁是”/login”.permitAll().successHandler(loginSuccessHandler()) //登錄成功后可使用loginSuccessHandler()存儲用戶信息,可選。.and().logout().logoutSuccessUrl("/home") //退出登錄后的默認網址是”/home”.permitAll().invalidateHttpSession(true).and().rememberMe()//登錄后記住用戶,下次自動登錄,數據庫中必須存在名為persistent_logins的表.tokenValiditySeconds(1209600);}@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { //指定密碼加密所使用的加密器為passwordEncoder() //需要將密碼加密后寫入數據庫 auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());auth.eraseCredentials(false); }@Beanpublic BCryptPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder(4);}@Beanpublic LoginSuccessHandler loginSuccessHandler(){return new LoginSuccessHandler();} }
    2、CustomUserDetailsService.java

    [java] view plaincopyprint?
  • package?security.support;??
  • ??
  • import?org.springframework.beans.factory.annotation.Autowired;??
  • 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.Component;??
  • ??
  • import?security.entity.SysUser;??
  • import?security.entity.User;??
  • import?security.service.UserService;??
  • @Component??
  • public?class?CustomUserDetailsService?implements?UserDetailsService?{??
  • ????@Autowired??//業務服務類??
  • ????private?UserService?userService;??
  • ??
  • ????@Override??
  • ????public?UserDetails?loadUserByUsername(String?userName)?throws?UsernameNotFoundException?{??
  • ????????//SysUser對應數據庫中的用戶表,是最終存儲用戶和密碼的表,可自定義??
  • ????????//本例使用SysUser中的name作為用戶名:??
  • ????????SysUser?user?=?userService.findByName(userName);??
  • ????????if?(user?==?null)?{??
  • ????????????throw?new?UsernameNotFoundException("UserName?"?+?userName?+?"?not?found");??
  • ????????}??
  • ????????//?SecurityUser實現UserDetails并將SysUser的name映射為username??
  • ????????SecurityUser?seu?=?new?SecurityUser(user);??
  • ????????return??seu;??
  • ????}??
  • ??
  • }??
  • package security.support;import org.springframework.beans.factory.annotation.Autowired; 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.Component;import security.entity.SysUser; import security.entity.User; import security.service.UserService; @Component public class CustomUserDetailsService implements UserDetailsService {@Autowired //業務服務類private UserService userService;@Overridepublic UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {//SysUser對應數據庫中的用戶表,是最終存儲用戶和密碼的表,可自定義//本例使用SysUser中的name作為用戶名:SysUser user = userService.findByName(userName);if (user == null) {throw new UsernameNotFoundException("UserName " + userName + " not found");}// SecurityUser實現UserDetails并將SysUser的name映射為usernameSecurityUser seu = new SecurityUser(user);return seu;}}
    3、SecurityUser.java

    [java] view plaincopyprint?
  • package?security.support;??
  • ??
  • import?java.util.ArrayList;??
  • import?java.util.Collection;??
  • import?java.util.HashSet;??
  • import?java.util.List;??
  • import?java.util.Set;??
  • ??
  • import?org.springframework.beans.factory.annotation.Autowired;??
  • import?org.springframework.security.core.GrantedAuthority;??
  • import?org.springframework.security.core.authority.SimpleGrantedAuthority;??
  • import?org.springframework.security.core.userdetails.UserDetails;??
  • ??
  • import?security.entity.SysRole<span?style="font-family:Arial,?Helvetica,?sans-serif;">;</span>??
  • import?security.entity.SysUser;??
  • ??
  • public?class?SecurityUser?extends?SysUser?implements?UserDetails?{??
  • ????private?static?final?long?serialVersionUID?=?1L;??
  • ????public?SecurityUser(SysUser?suser)?{??
  • ????????if(suser?!=?null)??
  • ????????{??
  • ????????????this.setId(suser.getId());??
  • ????????????this.setName(suser.getName());??
  • ????????????this.setEmail(suser.getEmail());??
  • ????????????this.setPassword(suser.getPassword());??
  • ????????????this.setDob(suser.getDob());??
  • ????????????this.setSysRoles(suser.getSysRoles());??
  • ????????}?????????
  • ????}??
  • ??????
  • ????@Override??
  • ????public?Collection<??extends?GrantedAuthority>?getAuthorities()?{??
  • ??????????
  • ????????Collection<GrantedAuthority>?authorities?=?new?ArrayList<>();??
  • ????????Set<SysRole>?userRoles?=?this.getSysRoles();??
  • ??????????
  • ????????if(userRoles?!=?null)??
  • ????????{??
  • ????????????for?(SysRole?role?:?userRoles)?{??
  • ????????????????SimpleGrantedAuthority?authority?=?new?SimpleGrantedAuthority(role.getName());??
  • ????????????????authorities.add(authority);??
  • ????????????}??
  • ????????}??
  • ????????return?authorities;??
  • ????}??
  • ??
  • ????@Override??
  • ????public?String?getPassword()?{??
  • ????????return?super.getPassword();??
  • ????}??
  • ??
  • ????@Override??
  • ????public?String?getUsername()?{??
  • ????????return?super.getName();??
  • ????}??
  • ??
  • ????@Override??
  • ????public?boolean?isAccountNonExpired()?{??
  • ????????return?true;??
  • ????}??
  • ??
  • ????@Override??
  • ????public?boolean?isAccountNonLocked()?{??
  • ????????return?true;??
  • ????}??
  • ??
  • ????@Override??
  • ????public?boolean?isCredentialsNonExpired()?{??
  • ????????return?true;??
  • ????}??
  • ??
  • ????@Override??
  • ????public?boolean?isEnabled()?{??
  • ????????return?true;??
  • ????}??
  • }??
  • package security.support;import java.util.ArrayList; import java.util.Collection; import java.util.HashSet; import java.util.List; import java.util.Set;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.authority.SimpleGrantedAuthority; import org.springframework.security.core.userdetails.UserDetails;import security.entity.SysRole; import security.entity.SysUser;public class SecurityUser extends SysUser implements UserDetails {private static final long serialVersionUID = 1L;public SecurityUser(SysUser suser) {if(suser != null){this.setId(suser.getId());this.setName(suser.getName());this.setEmail(suser.getEmail());this.setPassword(suser.getPassword());this.setDob(suser.getDob());this.setSysRoles(suser.getSysRoles());} }@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {Collection<GrantedAuthority> authorities = new ArrayList<>();Set<SysRole> userRoles = this.getSysRoles();if(userRoles != null){for (SysRole role : userRoles) {SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role.getName());authorities.add(authority);}}return authorities;}@Overridepublic String getPassword() {return super.getPassword();}@Overridepublic String getUsername() {return super.getName();}@Overridepublic boolean isAccountNonExpired() {return true;}@Overridepublic boolean isAccountNonLocked() {return true;}@Overridepublic boolean isCredentialsNonExpired() {return true;}@Overridepublic boolean isEnabled() {return true;} }
    4、LoginSuccessHandler.java

    [java] view plaincopyprint?
  • package?security.support;??
  • ??
  • import?java.io.IOException;??
  • import?java.util.Set;??
  • ??
  • import?javax.servlet.ServletException;??
  • import?javax.servlet.http.HttpServletRequest;??
  • import?javax.servlet.http.HttpServletResponse;??
  • ??
  • import?org.springframework.security.core.Authentication;??
  • import?org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;??
  • ??
  • import?security.entity.SysRole;??
  • import?security.entity.SysUser;??
  • ??
  • public?class?LoginSuccessHandler?extends??
  • ????????SavedRequestAwareAuthenticationSuccessHandler?{??
  • ????@Override????
  • ????public?void?onAuthenticationSuccess(HttpServletRequest?request,????
  • ????????????HttpServletResponse?response,?Authentication?authentication)?throws?IOException,????
  • ????????????ServletException?{????
  • ????????//獲得授權后可得到用戶信息???可使用SUserService進行數據庫操作??
  • ????????SysUser?userDetails?=?(SysUser)authentication.getPrincipal();????
  • ???????/*?Set<SysRole>?roles?=?userDetails.getSysRoles();*/??
  • ????????//輸出登錄提示信息????
  • ????????System.out.println("管理員?"?+?userDetails.getName()?+?"?登錄");????
  • ??????????
  • ????????System.out.println("IP?:"+getIpAddress(request));??
  • ????????????????
  • ????????super.onAuthenticationSuccess(request,?response,?authentication);????
  • ????}????
  • ??????
  • ????public?String?getIpAddress(HttpServletRequest?request){??????
  • ????????String?ip?=?request.getHeader("x-forwarded-for");??????
  • ????????if?(ip?==?null?||?ip.length()?==?0?||?"unknown".equalsIgnoreCase(ip))?{??????
  • ????????????ip?=?request.getHeader("Proxy-Client-IP");??????
  • ????????}??????
  • ????????if?(ip?==?null?||?ip.length()?==?0?||?"unknown".equalsIgnoreCase(ip))?{??????
  • ????????????ip?=?request.getHeader("WL-Proxy-Client-IP");??????
  • ????????}??????
  • ????????if?(ip?==?null?||?ip.length()?==?0?||?"unknown".equalsIgnoreCase(ip))?{??????
  • ????????????ip?=?request.getHeader("HTTP_CLIENT_IP");??????
  • ????????}??????
  • ????????if?(ip?==?null?||?ip.length()?==?0?||?"unknown".equalsIgnoreCase(ip))?{??????
  • ????????????ip?=?request.getHeader("HTTP_X_FORWARDED_FOR");??????
  • ????????}??????
  • ????????if?(ip?==?null?||?ip.length()?==?0?||?"unknown".equalsIgnoreCase(ip))?{??????
  • ????????????ip?=?request.getRemoteAddr();??????
  • ????????}??????
  • ????????return?ip;??????
  • ????}????
  • }??
  • package security.support;import java.io.IOException; import java.util.Set;import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;import org.springframework.security.core.Authentication; import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;import security.entity.SysRole; import security.entity.SysUser;public class LoginSuccessHandler extendsSavedRequestAwareAuthenticationSuccessHandler {@Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { //獲得授權后可得到用戶信息 可使用SUserService進行數據庫操作SysUser userDetails = (SysUser)authentication.getPrincipal(); /* Set<SysRole> roles = userDetails.getSysRoles();*///輸出登錄提示信息 System.out.println("管理員?" + userDetails.getName() + " 登錄"); System.out.println("IP :"+getIpAddress(request));super.onAuthenticationSuccess(request, response, authentication); } public String getIpAddress(HttpServletRequest request){ String ip = request.getHeader("x-forwarded-for"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return ip; } } 5、MvcConfig.java

    [java] view plaincopyprint?
  • package?security;??
  • ??
  • import?org.springframework.context.annotation.Configuration;??
  • import?org.springframework.web.servlet.config.annotation.ViewControllerRegistry;??
  • import?org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;??
  • ??
  • @Configuration??
  • public?class?MvcConfig?extends?WebMvcConfigurerAdapter?{??
  • ??
  • ????@Override??
  • ????public?void?addViewControllers(ViewControllerRegistry?registry)?{??
  • ????????registry.addViewController("/home").setViewName("home");??
  • ????????registry.addViewController("/").setViewName("home");??
  • ????????registry.addViewController("/hello").setViewName("hello");??
  • ????????registry.addViewController("/login").setViewName("login");??
  • ????}??
  • ??
  • }??
  • package security;import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;@Configuration public class MvcConfig extends WebMvcConfigurerAdapter {@Overridepublic void addViewControllers(ViewControllerRegistry registry) {registry.addViewController("/home").setViewName("home");registry.addViewController("/").setViewName("home");registry.addViewController("/hello").setViewName("hello");registry.addViewController("/login").setViewName("login");}}

    6、在resource下面創建templates目錄,然后放相關的html文件:

    home.html

    [html] view plaincopyprint?
  • <!DOCTYPE?html>??
  • <html?xmlns="http://www.w3.org/1999/xhtml"?xmlns:th="http://www.thymeleaf.org"?xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">??
  • ????<head>??
  • ????????<title>Spring?Security?Example</title>??
  • ????</head>??
  • ????<body>??
  • ????????<h1>Welcome!</h1>??
  • ??????????
  • ????????<p>Click?<a?th:href="@{/hello}">here</a>?to?see?a?greeting.</p>??
  • ????</body>??
  • </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-springsecurity3"><head><title>Spring Security Example</title></head><body><h1>Welcome!</h1><p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p></body> </html>hello.html
    [html] view plaincopyprint?
  • <!DOCTYPE?html>??
  • <html?xmlns="http://www.w3.org/1999/xhtml"?xmlns:th="http://www.thymeleaf.org"??
  • ??????xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">??
  • ????<head>??
  • ????????<title>Hello?World!</title>??
  • ????</head>??
  • ????<body>??
  • ????????<h1?th:inline="text">Hello?[[${#httpServletRequest.remoteUser}]]!</h1>??
  • ????????<form?th:action="@{/logout}"?method="post">??
  • ????????????<input?type="submit"?value="Sign?Out"/>??
  • ????????</form>??
  • ????</body>??
  • </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-springsecurity3"><head><title>Hello World!</title></head><body><h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1><form th:action="@{/logout}" method="post"><input type="submit" value="Sign Out"/></form></body> </html>login.html
    [html] view plaincopyprint?
  • <!DOCTYPE?html>??
  • <html?xmlns="http://www.w3.org/1999/xhtml"?xmlns:th="http://www.thymeleaf.org"??
  • ??????xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">??
  • ????<head>??
  • ????????<title>Spring?Security?Example?</title>??
  • ????</head>??
  • ????<body>??
  • ????????<div?th:if="${param.error}">??
  • ????????????Invalid?username?and?password.??
  • ????????</div>??
  • ????????<div?th:if="${param.logout}">??
  • ????????????You?have?been?logged?out.??
  • ????????</div>??
  • ????????<form?th:action="@{/login}"?method="post">??
  • ????????????<div><label>?User?Name?:?<input?type="text"?name="username"/>?</label></div>??
  • ????????????<div><label>?Password:?<input?type="password"?name="password"/>?</label></div>??
  • ????????????<div><input?type="submit"?value="Sign?In"/></div>??
  • ????????????<input?type="checkbox"?name="remember-me"?value="true"?th:checked="checked"/><p>Remember?me</p>??
  • ????????</form>??
  • ????</body>??
  • </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-springsecurity3"><head><title>Spring Security Example </title></head><body><div th:if="${param.error}">Invalid username and password.</div><div th:if="${param.logout}">You have been logged out.</div><form th:action="@{/login}" method="post"><div><label> User Name : <input type="text" name="username"/> </label></div><div><label> Password: <input type="password" name="password"/> </label></div><div><input type="submit" value="Sign In"/></div><input type="checkbox" name="remember-me" value="true" th:checked="checked"/><p>Remember?me</p></form></body> </html>接下來是主類:MainApplication.java

    [java] view plaincopyprint?
  • package?security;??
  • ??
  • import?org.springframework.boot.SpringApplication;??
  • import?org.springframework.boot.autoconfigure.SpringBootApplication;??
  • import?org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;??
  • import?org.springframework.web.servlet.config.annotation.ViewControllerRegistry;??
  • import?org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;??
  • ??
  • import?security.entity.SysUser;??
  • import?security.entity.User;??
  • import?security.service.UserService;??
  • import?security.Appctx;??
  • ??
  • @SpringBootApplication??
  • public?class?MainApplication{??
  • ????public?static?void?main(String[]?args)?{??
  • ????????//SpringApplication.run(MainApplication.class,?args);??
  • ????????SpringApplication?app=new?SpringApplication(MainApplication.class);???????
  • ??????????
  • ????????Appctx.ctx=app.run(args);??
  • ????????/*UserService?suserService?=?(UserService)?Appctx.ctx.getBean("suserService");?
  • ????????SysUser?su=?suserService.findByName("TEST");?
  • ????????BCryptPasswordEncoder?bc=new?BCryptPasswordEncoder(4);//將密碼加密?可以先設置初始密碼:000000??
  • ????????su.setPassword(bc.encode(su.getPassword()));//然后使用密碼為key值進行加密,運行主類后,會自動加密密碼,可連接數據庫查看。?
  • ????????System.out.println("密碼"+su.getPassword());?
  • ????????suserService.update(su);//運行一次后記得注釋這段重復加密會無法匹配*/??
  • ????}??
  • }??
  • package security;import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.web.servlet.config.annotation.ViewControllerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;import security.entity.SysUser; import security.entity.User; import security.service.UserService; import security.Appctx;@SpringBootApplication public class MainApplication{public static void main(String[] args) {//SpringApplication.run(MainApplication.class, args);SpringApplication app=new SpringApplication(MainApplication.class); Appctx.ctx=app.run(args);/*UserService suserService = (UserService) Appctx.ctx.getBean("suserService");SysUser su= suserService.findByName("TEST");BCryptPasswordEncoder bc=new BCryptPasswordEncoder(4);//將密碼加密 可以先設置初始密碼:000000 su.setPassword(bc.encode(su.getPassword()));//然后使用密碼為key值進行加密,運行主類后,會自動加密密碼,可連接數據庫查看。System.out.println("密碼"+su.getPassword());suserService.update(su);//運行一次后記得注釋這段重復加密會無法匹配*/} }
    Appctx.java

    [java] view plaincopyprint?
  • package?security.support;??
  • ??
  • import?org.springframework.context.ApplicationContext;??
  • ??
  • public?class?Appctx?{??
  • ????public?static?ApplicationContext?ctx=null;???
  • ????public?static?Object?getObject(String?string){??
  • ????????return?ctx.getBean(string);??
  • ????}??
  • }??
  • package security.support;import org.springframework.context.ApplicationContext;public class Appctx {public static ApplicationContext ctx=null; public static Object getObject(String string){return ctx.getBean(string);} }

    1.?運行,訪問http://localhost:8080/hello,系統出現如下界面:


    登陸成功后:

    登陸擁有ADMIN權限的用戶,可以進入/home

    如果用戶不具有權限,會出現以下:

    好了,根據配置:.antMatchers("/hello").hasAuthority("ADMIN")。來進行權限控制,就到這里,下面,我們來根據數據庫中的資源和權限的關系,進行授權和認證


    1、CustomInvocationSecurityMetadataSourceService.java 參照流程圖

    [java] view plaincopyprint?
  • /*?
  • ?*?@(#)?MyInvocationSecurityMetadataSourceService.java??2011-3-23?下午02:58:29?
  • ?*?
  • ?*?Copyright?2011?by?Sparta??
  • ?*/??
  • ??
  • package?security.support;??
  • ??
  • import?java.util.ArrayList;??
  • import?java.util.Collection;??
  • import?java.util.HashMap;??
  • import?java.util.Iterator;??
  • import?java.util.List;??
  • import?java.util.Map;??
  • import?java.util.Map.Entry;??
  • import?java.util.Set;??
  • ??
  • import?javax.annotation.PostConstruct;??
  • ??
  • import?org.hibernate.Session;??
  • import?org.hibernate.SessionFactory;??
  • import?org.springframework.beans.factory.annotation.Autowired;??
  • import?org.springframework.context.ApplicationContext;??
  • import?org.springframework.context.support.ClassPathXmlApplicationContext;??
  • import?org.springframework.security.access.ConfigAttribute;??
  • import?org.springframework.security.access.SecurityConfig;??
  • import?org.springframework.security.core.GrantedAuthority;??
  • import?org.springframework.security.core.context.SecurityContextHolder;??
  • import?org.springframework.security.core.userdetails.UserDetails;??
  • import?org.springframework.security.web.FilterInvocation;??
  • import?org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;??
  • import?org.springframework.security.web.util.matcher.AntPathRequestMatcher;??
  • import?org.springframework.security.web.util.matcher.RequestMatcher;??
  • import?org.springframework.stereotype.Component;??
  • import?org.springframework.stereotype.Service;??
  • ??
  • import?security.dao.SResourceVODao;??
  • import?security.dao.SRoleDao;??
  • import?security.dao.SRoleVODao;??
  • import?security.entity.SRole;??
  • import?security.service.SResourceService;??
  • import?security.service.SRoleService;??
  • ??
  • /**?
  • ?*?最核心的地方,就是提供某個資源對應的權限定義,即getAttributes方法返回的結果。?此類在初始化時,應該取到所有資源及其對應角色的定義。?
  • ?*??
  • ?*/??
  • @Service??
  • public?class?CustomInvocationSecurityMetadataSourceService?implements??
  • ????????FilterInvocationSecurityMetadataSource?{??
  • ??????
  • ????@Autowired??
  • ????private?SResourceVODao?sResourceVODao;??
  • ??????
  • ????@Autowired??
  • ????private?SRoleVODao?sRoleVODao;??
  • ??????
  • ????private?static?Map<String,?Collection<ConfigAttribute>>?resourceMap?=?null;??
  • ??
  • ????/*public?CustomInvocationSecurityMetadataSourceService(SResourceService?sres,SRoleService?sR)?{?
  • ????????this.sResourceService?=?sres;?
  • ????????this.sRoleService?=?sR;?
  • ????????loadResourceDefine();?
  • ????}*/??
  • ????@PostConstruct<span?style="color:#33cc00;">//<span?style="font-family:Helvetica,?Tahoma,?Arial,?sans-serif;font-size:14px;line-height:25.1875px;">??</span><span?style="font-family:Helvetica,?Tahoma,?Arial,?sans-serif;line-height:25.1875px;"><span?style="font-size:10px;">被@PostConstruct修飾的方法會在服務器加載Servle的時候運行,并且只會被服務器執行一次。PostConstruct在構造函數之后執行,init()方法之前執行。</span></span></span>??
  • ????private?void?loadResourceDefine()?{??<span?style="color:#33cc00;">?//一定要加上<span?style="font-family:Arial,?Helvetica,?sans-serif;">@PostConstruct注解</span></span>??
  • ????<span?style="color:#33cc00;">//?在Web服務器啟動時,提取系統中的所有權限。</span>??
  • ????????List<Map<String,Object>>?list?=sRoleVODao.findAll();??
  • ????????List<String>?query?=?new?ArrayList<String>();??
  • ????????if(list!=null?&&?list.size()>0)?{??
  • ????????????for(Map<String,Object>?sr?:list){??
  • ????????????????//String?name?=?sr.get("name")????
  • ????????????????Object?value?=?sr.get("name");??
  • ????????????????String?name?=?String.valueOf(value);??
  • ????????????????query.add(name);??
  • ????????????}??
  • ????????}??
  • ????????<span?style="color:#33cc00;">/*?
  • ?????????*?應當是資源為key,?權限為value。?資源通常為url,?權限就是那些以ROLE_為前綴的角色。?一個資源可以由多個權限來訪問。?
  • ?????????*?sparta?
  • ?????????*/</span>??
  • ????????resourceMap?=?new?HashMap<String,?Collection<ConfigAttribute>>();??
  • ??
  • ????????for?(String?auth?:?query)?{??
  • ????????????ConfigAttribute?ca?=?new?SecurityConfig(auth);??
  • ????????????//List<Map<String,Object>>?query1?=?sResourceVODao.findByRoleName(auth);??
  • ????????????List<String>?query1?=?new?ArrayList<String>();??
  • ????????????List<Map<String,?Object>>??list1?=?sResourceVODao.findByRoleName(auth);??
  • ????????????if(list1!=null?&&?list1.size()>0)?{??
  • ????????????????for(Map<String,?Object>?map?:list1){??
  • ????????????????????Object?value?=?map.get("resource_string");??
  • ????????????????????String?url?=?String.valueOf(value);??
  • ????????????????????query1.add(url);??
  • ????????????????}??
  • ????????????}??
  • ????????????for?(String?res?:?query1)?{??
  • ????????????????String?url?=?res;??
  • ??????????????????
  • ????????????????<span?style="color:#33cc00;">/*?
  • ?????????????????*?判斷資源文件和權限的對應關系,如果已經存在相關的資源url,則要通過該url為key提取出權限集合,將權限增加到權限集合中。?
  • ?????????????????*?sparta?
  • ?????????????????*/</span>??
  • ????????????????if?(resourceMap.containsKey(url))?{??
  • ??
  • ????????????????????Collection<ConfigAttribute>?value?=?resourceMap.get(url);??
  • ????????????????????value.add(ca);??
  • ????????????????????resourceMap.put(url,?value);??
  • ????????????????}?else?{??
  • ????????????????????Collection<ConfigAttribute>?atts?=?new?ArrayList<ConfigAttribute>();??
  • ????????????????????atts.add(ca);??
  • ????????????????????resourceMap.put(url,?atts);??
  • ????????????????}??
  • ??
  • ????????????}??
  • ????????}??
  • ??
  • ????}??
  • ??
  • ????@Override??
  • ????public?Collection<ConfigAttribute>?getAllConfigAttributes()?{??
  • ?????????return?new?ArrayList<ConfigAttribute>();??
  • ????}??
  • <span?style="color:#33cc00;">??
  • ????//?根據URL,找到相關的權限配置。</span>??
  • ????@Override??
  • ????public?Collection<ConfigAttribute>?getAttributes(Object?object)??
  • ????????????throws?IllegalArgumentException?{??
  • ????????System.out.println("nwuidhwuiehdfu");??
  • ????????<span?style="color:#33cc00;">//?object?是一個URL,被用戶請求的url。</span>??
  • ????????FilterInvocation?filterInvocation?=?(FilterInvocation)?object;??
  • ????????if?(resourceMap?==?null)?{??
  • ????????????loadResourceDefine();??
  • ????????}??
  • ????????Iterator<String>?ite?=?resourceMap.keySet().iterator();??
  • ????????while?(ite.hasNext())?{??
  • ????????????String?resURL?=?ite.next();??
  • ?????????????RequestMatcher?requestMatcher?=?new?AntPathRequestMatcher(resURL);??
  • ????????????????if(requestMatcher.matches(filterInvocation.getHttpRequest()))?{??
  • ????????????????return?resourceMap.get(resURL);??
  • ????????????}??
  • ????????}??
  • ??
  • ????????return?null;??
  • ????}??
  • ????@Override??
  • ????public?boolean?supports(Class<?>?arg0)?{??
  • ??
  • ????????return?true;??
  • ????}??
  • ??
  • }??
  • /** @(#) MyInvocationSecurityMetadataSourceService.java 2011-3-23 下午02:58:29** Copyright 2011 by Sparta */package security.support;import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Map.Entry; import java.util.Set;import javax.annotation.PostConstruct;import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.support.ClassPathXmlApplicationContext; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.core.GrantedAuthority; import org.springframework.security.core.context.SecurityContextHolder; import org.springframework.security.core.userdetails.UserDetails; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import org.springframework.security.web.util.matcher.AntPathRequestMatcher; import org.springframework.security.web.util.matcher.RequestMatcher; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service;import security.dao.SResourceVODao; import security.dao.SRoleDao; import security.dao.SRoleVODao; import security.entity.SRole; import security.service.SResourceService; import security.service.SRoleService;/*** 最核心的地方,就是提供某個資源對應的權限定義,即getAttributes方法返回的結果。 此類在初始化時,應該取到所有資源及其對應角色的定義。* */ @Service public class CustomInvocationSecurityMetadataSourceService implementsFilterInvocationSecurityMetadataSource {@Autowiredprivate SResourceVODao sResourceVODao;@Autowiredprivate SRoleVODao sRoleVODao;private static Map<String, Collection<ConfigAttribute>> resourceMap = null;/*public CustomInvocationSecurityMetadataSourceService(SResourceService sres,SRoleService sR) {this.sResourceService = sres;this.sRoleService = sR;loadResourceDefine();}*/@PostConstruct//? 被@PostConstruct修飾的方法會在服務器加載Servle的時候運行,并且只會被服務器執行一次。PostConstruct在構造函數之后執行,init()方法之前執行。private void loadResourceDefine() { //一定要加上@PostConstruct注解// 在Web服務器啟動時,提取系統中的所有權限。List<Map<String,Object>> list =sRoleVODao.findAll();List<String> query = new ArrayList<String>();if(list!=null && list.size()>0) {for(Map<String,Object> sr :list){//String name = sr.get("name") Object value = sr.get("name");String name = String.valueOf(value);query.add(name);}}/** 應當是資源為key, 權限為value。 資源通常為url, 權限就是那些以ROLE_為前綴的角色。 一個資源可以由多個權限來訪問。* sparta*/resourceMap = new HashMap<String, Collection<ConfigAttribute>>();for (String auth : query) {ConfigAttribute ca = new SecurityConfig(auth);//List<Map<String,Object>> query1 = sResourceVODao.findByRoleName(auth);List<String> query1 = new ArrayList<String>();List<Map<String, Object>> list1 = sResourceVODao.findByRoleName(auth);if(list1!=null && list1.size()>0) {for(Map<String, Object> map :list1){Object value = map.get("resource_string");String url = String.valueOf(value);query1.add(url);}}for (String res : query1) {String url = res;/** 判斷資源文件和權限的對應關系,如果已經存在相關的資源url,則要通過該url為key提取出權限集合,將權限增加到權限集合中。* sparta*/if (resourceMap.containsKey(url)) {Collection<ConfigAttribute> value = resourceMap.get(url);value.add(ca);resourceMap.put(url, value);} else {Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();atts.add(ca);resourceMap.put(url, atts);}}}}@Overridepublic Collection<ConfigAttribute> getAllConfigAttributes() {return new ArrayList<ConfigAttribute>();} // 根據URL,找到相關的權限配置。@Overridepublic Collection<ConfigAttribute> getAttributes(Object object)throws IllegalArgumentException {System.out.println("nwuidhwuiehdfu");// object 是一個URL,被用戶請求的url。FilterInvocation filterInvocation = (FilterInvocation) object;if (resourceMap == null) {loadResourceDefine();}Iterator<String> ite = resourceMap.keySet().iterator();while (ite.hasNext()) {String resURL = ite.next();RequestMatcher requestMatcher = new AntPathRequestMatcher(resURL);if(requestMatcher.matches(filterInvocation.getHttpRequest())) {return resourceMap.get(resURL);}}return null;}@Overridepublic boolean supports(Class<?> arg0) {return true;}} 2、CustomAccessDecisionManager.java

    [html] view plaincopyprint?
  • /*??
  • ?*?@(#)?MyAccessDecisionManager.java??2011-3-23?下午04:41:12??
  • ?*??
  • ?*?Copyright?2011?by?Sparta???
  • ?*/??
  • ??
  • package?security.support;??
  • ??
  • import?java.util.Collection;??
  • import?java.util.Iterator;??
  • ??
  • import?org.springframework.security.access.AccessDecisionManager;??
  • import?org.springframework.security.access.AccessDeniedException;??
  • import?org.springframework.security.access.ConfigAttribute;??
  • import?org.springframework.security.access.SecurityConfig;??
  • import?org.springframework.security.authentication.InsufficientAuthenticationException;??
  • import?org.springframework.security.core.Authentication;??
  • import?org.springframework.security.core.GrantedAuthority;??
  • import?org.springframework.stereotype.Component;??
  • import?org.springframework.stereotype.Service;??
  • ??
  • <span?style="color:#33cc00;">/**??
  • ?*AccessdecisionManager在Spring?security中是很重要的。??
  • ?*??
  • ?*在驗證部分簡略提過了,所有的Authentication實現需要保存在一個GrantedAuthority對象數組中。???
  • ?*這就是賦予給主體的權限。?GrantedAuthority對象通過AuthenticationManager??
  • ?*保存到?Authentication對象里,然后從AccessDecisionManager讀出來,進行授權判斷。???
  • ?*??
  • ?*Spring?Security提供了一些攔截器,來控制對安全對象的訪問權限,例如方法調用或web請求。???
  • ?*一個是否允許執行調用的預調用決定,是由AccessDecisionManager實現的。???
  • ?*這個?AccessDecisionManager?被AbstractSecurityInterceptor調用,??
  • ?*它用來作最終訪問控制的決定。?這個AccessDecisionManager接口包含三個方法:???
  • ?*??
  • ?void?decide(Authentication?authentication,?Object?secureObject,??
  • ????List<ConfigAttributeDefinition>?config)?throws?AccessDeniedException;??
  • ?boolean?supports(ConfigAttribute?attribute);??
  • ?boolean?supports(Class?clazz);??
  • ???
  • ??從第一個方法可以看出來,AccessDecisionManager使用方法參數傳遞所有信息,這好像在認證評估時進行決定。???
  • ??特別是,在真實的安全方法期望調用的時候,傳遞安全Object啟用那些參數。???
  • ??比如,讓我們假設安全對象是一個MethodInvocation。???
  • ??很容易為任何Customer參數查詢MethodInvocation,??
  • ??然后在AccessDecisionManager里實現一些有序的安全邏輯,來確認主體是否允許在那個客戶上操作。???
  • ??如果訪問被拒絕,實現將拋出一個AccessDeniedException異常。??
  • ??
  • ??這個?supports(ConfigAttribute)?方法在啟動的時候被??
  • ??AbstractSecurityInterceptor調用,來決定AccessDecisionManager??
  • ??是否可以執行傳遞ConfigAttribute。???
  • ??supports(Class)方法被安全攔截器實現調用,??
  • ??包含安全攔截器將顯示的AccessDecisionManager支持安全對象的類型。??
  • ?*/</span>??
  • @Service??
  • public?class?CustomAccessDecisionManager?implements?AccessDecisionManager?{??
  • ??????
  • ????public?void?decide(?Authentication?authentication,?Object?object,???
  • ????????????Collection<ConfigAttribute>?configAttributes)???
  • ????????throws?AccessDeniedException,?InsufficientAuthenticationException{??
  • ????????if(?configAttributes?==?null?)?{??
  • ????????????return?;??
  • ????????}??
  • ??????????
  • ????????Iterator<ConfigAttribute>?ite?=?configAttributes.iterator();??
  • ??????????
  • ????????while(?ite.hasNext()){??
  • ????????????ConfigAttribute?ca?=?ite.next();??
  • ????????????String?needRole?=?((SecurityConfig)ca).getAttribute();??
  • ??????????????
  • ????????<span?style="color:#33cc00;">???//ga?為用戶所被賦予的權限。?needRole?為訪問相應的資源應該具有的權限。</span>??
  • ????????????for(?GrantedAuthority?ga:?authentication.getAuthorities()){??
  • ??????????????????
  • ????????????????if(needRole.trim().equals(ga.getAuthority().trim())){??
  • ??
  • ????????????????????return;??
  • ????????????????}??
  • ??????????????????
  • ????????????}??
  • ??????????????
  • ????????}??
  • ??????????
  • ????????throw?new?AccessDeniedException("權限不足");??
  • ??????????
  • ????}??
  • ??????
  • ????public?boolean?supports(?ConfigAttribute?attribute?){??
  • ????????<span?style="color:#ff0000;">return?true;</span><span?style="color:#33cc00;">//都要設為true</span>??
  • ??
  • ????}??
  • ??????
  • ????public?boolean?supports(Class<?>?clazz){??
  • ????????<span?style="color:#ff0000;">return?true;</span><span?style="color:rgb(51,204,0);font-family:Arial,?Helvetica,?sans-serif;">//都要設為true</span>??
  • ????}??
  • ??????
  • ??
  • }??
  • /** @(#) MyAccessDecisionManager.java 2011-3-23 下午04:41:12** Copyright 2011 by Sparta */package security.support;import java.util.Collection; import java.util.Iterator;import org.springframework.security.access.AccessDecisionManager; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityConfig; import org.springframework.security.authentication.InsufficientAuthenticationException; import org.springframework.security.core.Authentication; import org.springframework.security.core.GrantedAuthority; import org.springframework.stereotype.Component; import org.springframework.stereotype.Service;/***AccessdecisionManager在Spring security中是很重要的。**在驗證部分簡略提過了,所有的Authentication實現需要保存在一個GrantedAuthority對象數組中。 *這就是賦予給主體的權限。 GrantedAuthority對象通過AuthenticationManager*保存到 Authentication對象里,然后從AccessDecisionManager讀出來,進行授權判斷。 **Spring Security提供了一些攔截器,來控制對安全對象的訪問權限,例如方法調用或web請求。 *一個是否允許執行調用的預調用決定,是由AccessDecisionManager實現的。 *這個 AccessDecisionManager 被AbstractSecurityInterceptor調用,*它用來作最終訪問控制的決定。 這個AccessDecisionManager接口包含三個方法: *void decide(Authentication authentication, Object secureObject,List<ConfigAttributeDefinition> config) throws AccessDeniedException;boolean supports(ConfigAttribute attribute);boolean supports(Class clazz);從第一個方法可以看出來,AccessDecisionManager使用方法參數傳遞所有信息,這好像在認證評估時進行決定。 特別是,在真實的安全方法期望調用的時候,傳遞安全Object啟用那些參數。 比如,讓我們假設安全對象是一個MethodInvocation。 很容易為任何Customer參數查詢MethodInvocation,然后在AccessDecisionManager里實現一些有序的安全邏輯,來確認主體是否允許在那個客戶上操作。 如果訪問被拒絕,實現將拋出一個AccessDeniedException異常。這個 supports(ConfigAttribute) 方法在啟動的時候被AbstractSecurityInterceptor調用,來決定AccessDecisionManager是否可以執行傳遞ConfigAttribute。 supports(Class)方法被安全攔截器實現調用,包含安全攔截器將顯示的AccessDecisionManager支持安全對象的類型。*/ @Service public class CustomAccessDecisionManager implements AccessDecisionManager {public void decide( Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes) throws AccessDeniedException, InsufficientAuthenticationException{if( configAttributes == null ) {return ;}Iterator<ConfigAttribute> ite = configAttributes.iterator();while( ite.hasNext()){ConfigAttribute ca = ite.next();String needRole = ((SecurityConfig)ca).getAttribute(); //ga 為用戶所被賦予的權限。 needRole 為訪問相應的資源應該具有的權限。for( GrantedAuthority ga: authentication.getAuthorities()){if(needRole.trim().equals(ga.getAuthority().trim())){return;}}}throw new AccessDeniedException("權限不足");}public boolean supports( ConfigAttribute attribute ){return true;//都要設為true}public boolean supports(Class<?> clazz){return true;//都要設為true}}

    3、?MyFilterSecurityInterceptor.java

    [java] view plaincopyprint?
  • /*?
  • ?*?@(#)?MyFilterSecurityInterceptor.java??2011-3-23?上午07:53:03?
  • ?*?
  • ?*?Copyright?2011?by?Sparta??
  • ?*/??
  • ??
  • package?security.support;??
  • ??
  • import?java.io.IOException;??
  • import?java.util.Collection;??
  • import?java.util.Map;??
  • ??
  • import?javax.annotation.PostConstruct;??
  • import?javax.servlet.Filter;??
  • import?javax.servlet.FilterChain;??
  • import?javax.servlet.FilterConfig;??
  • import?javax.servlet.ServletException;??
  • import?javax.servlet.ServletRequest;??
  • import?javax.servlet.ServletResponse;??
  • ??
  • import?org.springframework.beans.factory.annotation.Autowired;??
  • import?org.springframework.security.access.ConfigAttribute;??
  • import?org.springframework.security.access.SecurityMetadataSource;??
  • import?org.springframework.security.access.intercept.AbstractSecurityInterceptor;??
  • import?org.springframework.security.access.intercept.InterceptorStatusToken;??
  • import?org.springframework.security.authentication.AuthenticationManager;??
  • import?org.springframework.security.web.FilterInvocation;??
  • import?org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;??
  • import?security.service.SResourceService;??
  • ??
  • /**?
  • ?*?該過濾器的主要作用就是通過spring著名的IoC生成securityMetadataSource。?
  • ?*?securityMetadataSource相當于本包中自定義的MyInvocationSecurityMetadataSourceService。?
  • ?*?該MyInvocationSecurityMetadataSourceService的作用提從數據庫提取權限和資源,裝配到HashMap中,?
  • ?*?供Spring?Security使用,用于權限校驗。?
  • ?*?@author?sparta?11/3/29?
  • ?*?
  • ?*/??
  • @Component??
  • public?class?MySecurityFilter???
  • ????extends?AbstractSecurityInterceptor??
  • ????implements?Filter{??
  • ????@Autowired??
  • ????private?CustomInvocationSecurityMetadataSourceService??mySecurityMetadataSource;??
  • ??????
  • ????@Autowired??
  • ????private?CustomAccessDecisionManager?myAccessDecisionManager;??
  • ??????
  • ????@Autowired??
  • ????private?AuthenticationManager?authenticationManager;??
  • ??????
  • ??????
  • ????@PostConstruct??
  • ????public?void?init(){??
  • ????????super.setAuthenticationManager(authenticationManager);??
  • ????????super.setAccessDecisionManager(myAccessDecisionManager);??
  • ????}??
  • ??????
  • ????public?void?doFilter(?ServletRequest?request,?ServletResponse?response,?FilterChain?chain)??
  • ????throws?IOException,?ServletException{??
  • ????????FilterInvocation?fi?=?new?FilterInvocation(?request,?response,?chain?);??
  • ????????invoke(fi);??
  • ??????????
  • ????}??
  • ??
  • ??????
  • ????public?Class<??extends?Object>?getSecureObjectClass(){??
  • ????????return?FilterInvocation.class;??
  • ????}??
  • ??
  • ??????
  • ????public?void?invoke(?FilterInvocation?fi?)?throws?IOException,?ServletException{??
  • ????????System.out.println("filter..........................");??
  • ????????InterceptorStatusToken??token?=?super.beforeInvocation(fi);??
  • ????????try{??
  • ????????????fi.getChain().doFilter(fi.getRequest(),?fi.getResponse());??
  • ????????}finally{??
  • ????????????super.afterInvocation(token,?null);??
  • ????????}??
  • ??????????
  • ????}??
  • ??????????
  • ??????
  • ????@Override??
  • ????public?SecurityMetadataSource?obtainSecurityMetadataSource(){??
  • ????????System.out.println("filtergergetghrthetyetyetyetyj");??
  • ????????return?this.mySecurityMetadataSource;??
  • ????}??
  • ??????
  • ????public?void?destroy(){??
  • ????????System.out.println("filter===========================end");??
  • ????}??
  • ????public?void?init(?FilterConfig?filterconfig?)?throws?ServletException{??
  • ????????System.out.println("filter===========================");??
  • ????}??
  • }??
  • /** @(#) MyFilterSecurityInterceptor.java 2011-3-23 上午07:53:03** Copyright 2011 by Sparta */package security.support;import java.io.IOException; import java.util.Collection; import java.util.Map;import javax.annotation.PostConstruct; import javax.servlet.Filter; import javax.servlet.FilterChain; import javax.servlet.FilterConfig; import javax.servlet.ServletException; import javax.servlet.ServletRequest; import javax.servlet.ServletResponse;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.security.access.ConfigAttribute; import org.springframework.security.access.SecurityMetadataSource; import org.springframework.security.access.intercept.AbstractSecurityInterceptor; import org.springframework.security.access.intercept.InterceptorStatusToken; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.web.FilterInvocation; import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource; import security.service.SResourceService;/*** 該過濾器的主要作用就是通過spring著名的IoC生成securityMetadataSource。* securityMetadataSource相當于本包中自定義的MyInvocationSecurityMetadataSourceService。* 該MyInvocationSecurityMetadataSourceService的作用提從數據庫提取權限和資源,裝配到HashMap中,* 供Spring Security使用,用于權限校驗。* @author sparta 11/3/29**/ @Component public class MySecurityFilter extends AbstractSecurityInterceptorimplements Filter{@Autowiredprivate CustomInvocationSecurityMetadataSourceService mySecurityMetadataSource;@Autowiredprivate CustomAccessDecisionManager myAccessDecisionManager;@Autowiredprivate AuthenticationManager authenticationManager;@PostConstructpublic void init(){super.setAuthenticationManager(authenticationManager);super.setAccessDecisionManager(myAccessDecisionManager);}public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain)throws IOException, ServletException{FilterInvocation fi = new FilterInvocation( request, response, chain );invoke(fi);}public Class<? extends Object> getSecureObjectClass(){return FilterInvocation.class;}public void invoke( FilterInvocation fi ) throws IOException, ServletException{System.out.println("filter..........................");InterceptorStatusToken token = super.beforeInvocation(fi);try{fi.getChain().doFilter(fi.getRequest(), fi.getResponse());}finally{super.afterInvocation(token, null);}}@Overridepublic SecurityMetadataSource obtainSecurityMetadataSource(){System.out.println("filtergergetghrthetyetyetyetyj");return this.mySecurityMetadataSource;}public void destroy(){System.out.println("filter===========================end");}public void init( FilterConfig filterconfig ) throws ServletException{System.out.println("filter===========================");} }
    接下來修改一個類的 大家注意:
    WebSecurityConfig.java

    [java] view plaincopyprint?
  • package?security;??
  • ??
  • import?org.springframework.beans.factory.annotation.Autowired;??
  • import?org.springframework.boot.autoconfigure.security.SecurityProperties;??
  • import?org.springframework.boot.web.servlet.FilterRegistrationBean;??
  • import?org.springframework.context.annotation.Bean;??
  • import?org.springframework.context.annotation.Configuration;??
  • import?org.springframework.core.annotation.Order;??
  • import?org.springframework.security.authentication.AuthenticationManager;??
  • import?org.springframework.security.authentication.AuthenticationProvider;??
  • import?org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;??
  • import?org.springframework.security.config.annotation.web.builders.HttpSecurity;??
  • import?org.springframework.security.config.annotation.web.builders.WebSecurity;??
  • import?org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;??
  • import?org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;??
  • import?org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;??
  • import?org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;??
  • import?org.springframework.security.web.access.intercept.FilterSecurityInterceptor;??
  • ??
  • import?security.support.CustomUserDetailsService;??
  • import?security.support.LoginSuccessHandler;??
  • import?security.support.MySecurityFilter;??
  • @Configuration??
  • @EnableWebSecurity??
  • public?class?WebSecurityConfig?extends?WebSecurityConfigurerAdapter?{??
  • ??????
  • ????@Autowired??
  • ????private?MyFilterSecurityInterceptor?mySecurityFilter;??
  • ??????
  • ????@Autowired??
  • ????private?CustomUserDetailsService?customUserDetailsService;??
  • ??????
  • ????@Override??
  • ????public?AuthenticationManager?authenticationManagerBean()?throws?Exception?{??
  • ???????
  • ????return?super.authenticationManagerBean();??
  • ???????
  • ????}??
  • ????//http://localhost:8080/login?輸入正確的用戶名密碼?并且選中remember-me?則登陸成功,轉到?index頁面???
  • ????//再次訪問index頁面無需登錄直接訪問??
  • ????//訪問http://localhost:8080/home?不攔截,直接訪問,??
  • ????//訪問http://localhost:8080/hello?需要登錄驗證后,且具備?“ADMIN”權限hasAuthority("ADMIN")才可以訪問??
  • ????@Override??
  • ????protected?void?configure(HttpSecurity?http)?throws?Exception?{??
  • ????????http??
  • ????????.addFilterBefore(mySecurityFilter,?FilterSecurityInterceptor.class)//在正確的位置添加我們自定義的過濾器??
  • ????????.authorizeRequests()??
  • ????????.antMatchers("/home").permitAll()??
  • ????????.anyRequest().authenticated()??
  • ????????//.antMatchers("/hello").hasAuthority("ADMIN")??
  • ????????.and()??
  • ????????.formLogin()??
  • ????????.loginPage("/login")??????
  • ????????.permitAll()??
  • ????????.successHandler(loginSuccessHandler())//code3??
  • ????????.and()??
  • ????????.logout()??
  • ????????.logoutSuccessUrl("/home")??
  • ????????.permitAll()??
  • ????????.invalidateHttpSession(true)??
  • ????????.and()??
  • ????????.rememberMe()??
  • ????????.tokenValiditySeconds(1209600);??
  • ????}??
  • ????@Override??
  • ????????public?void?configure(WebSecurity?web)?throws?Exception?{??
  • ????????????super.configure(web);??
  • ????}??
  • ????@Autowired??
  • ????public?void?configureGlobal(AuthenticationManagerBuilder?auth)?throws?Exception?{?????
  • //指定密碼加密所使用的加密器為passwordEncoder()??
  • //需要將密碼加密后寫入數據庫???
  • ????auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());??
  • //不刪除憑據,以便記住用戶??
  • ????????auth.eraseCredentials(false);?????????
  • ????}??
  • ??????
  • ????//?Code5----------------------------------------------??
  • ????@Bean??
  • ????public?BCryptPasswordEncoder?passwordEncoder()?{??
  • ????????return?new?BCryptPasswordEncoder(4);??
  • ????}??
  • ??
  • ????//?Code3----------------------------------------------??
  • ????@Bean??
  • ????public?LoginSuccessHandler?loginSuccessHandler(){??
  • ????????return?new?LoginSuccessHandler();??
  • ????}??
  • }??
  • package security;import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.security.SecurityProperties; import org.springframework.boot.web.servlet.FilterRegistrationBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.annotation.Order; import org.springframework.security.authentication.AuthenticationManager; import org.springframework.security.authentication.AuthenticationProvider; import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; import org.springframework.security.config.annotation.web.builders.HttpSecurity; import org.springframework.security.config.annotation.web.builders.WebSecurity; import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;import security.support.CustomUserDetailsService; import security.support.LoginSuccessHandler; import security.support.MySecurityFilter; @Configuration @EnableWebSecurity public class WebSecurityConfig extends WebSecurityConfigurerAdapter {@Autowiredprivate MyFilterSecurityInterceptor mySecurityFilter;@Autowiredprivate CustomUserDetailsService customUserDetailsService;@Overridepublic AuthenticationManager authenticationManagerBean() throws Exception {return super.authenticationManagerBean();}//http://localhost:8080/login 輸入正確的用戶名密碼 并且選中remember-me 則登陸成功,轉到 index頁面 //再次訪問index頁面無需登錄直接訪問//訪問http://localhost:8080/home 不攔截,直接訪問,//訪問http://localhost:8080/hello 需要登錄驗證后,且具備 “ADMIN”權限hasAuthority("ADMIN")才可以訪問@Overrideprotected void configure(HttpSecurity http) throws Exception {http.addFilterBefore(mySecurityFilter, FilterSecurityInterceptor.class)//在正確的位置添加我們自定義的過濾器.authorizeRequests().antMatchers("/home").permitAll().anyRequest().authenticated()//.antMatchers("/hello").hasAuthority("ADMIN").and().formLogin().loginPage("/login") .permitAll().successHandler(loginSuccessHandler())//code3.and().logout().logoutSuccessUrl("/home").permitAll().invalidateHttpSession(true).and().rememberMe().tokenValiditySeconds(1209600);}@Overridepublic void configure(WebSecurity web) throws Exception {super.configure(web);}@Autowiredpublic void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { //指定密碼加密所使用的加密器為passwordEncoder() //需要將密碼加密后寫入數據庫 auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder()); //不刪除憑據,以便記住用戶auth.eraseCredentials(false); }// Code5----------------------------------------------@Beanpublic BCryptPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder(4);}// Code3----------------------------------------------@Beanpublic LoginSuccessHandler loginSuccessHandler(){return new LoginSuccessHandler();} }
    ServletInitializer.java

    [java] view plaincopyprint?
  • package?security;??
  • ??
  • import?javax.servlet.FilterRegistration;??
  • import?javax.servlet.ServletContext;??
  • import?javax.servlet.ServletException;??
  • ??
  • import?org.springframework.boot.builder.SpringApplicationBuilder;??
  • import?org.springframework.boot.web.support.SpringBootServletInitializer;??
  • import?org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;??
  • ??
  • public?class?ServletInitializer?extends?SpringBootServletInitializer?{??
  • ??
  • ????@Override??
  • ????protected?SpringApplicationBuilder?configure(SpringApplicationBuilder?application)?{??
  • ????????return?application.sources(MainApplication.class);??
  • ????}??
  • ??????
  • ????@Override??
  • ????public?void?onStartup(ServletContext?servletContext)??
  • ????throws?ServletException?{??
  • ?????FilterRegistration.Dynamic?openEntityManagerInViewFilter?=?servletContext.addFilter("openEntityManagerInViewFilter",?OpenEntityManagerInViewFilter.class);??
  • ?????????openEntityManagerInViewFilter.setInitParameter("entityManagerFactoryBeanName","entityManagerFactory");??
  • ?????????openEntityManagerInViewFilter.addMappingForUrlPatterns(null,?false,?"/*");??
  • ????super.onStartup(servletContext);??
  • ????}??
  • }??
  • package security;import javax.servlet.FilterRegistration; import javax.servlet.ServletContext; import javax.servlet.ServletException;import org.springframework.boot.builder.SpringApplicationBuilder; import org.springframework.boot.web.support.SpringBootServletInitializer; import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;public class ServletInitializer extends SpringBootServletInitializer {@Overrideprotected SpringApplicationBuilder configure(SpringApplicationBuilder application) {return application.sources(MainApplication.class);}@Overridepublic void onStartup(ServletContext servletContext)throws ServletException {FilterRegistration.Dynamic openEntityManagerInViewFilter = servletContext.addFilter("openEntityManagerInViewFilter", OpenEntityManagerInViewFilter.class);openEntityManagerInViewFilter.setInitParameter("entityManagerFactoryBeanName","entityManagerFactory");openEntityManagerInViewFilter.addMappingForUrlPatterns(null, false, "/*");super.onStartup(servletContext);} }
    還有主類需要修改

    [java] view plaincopyprint?
  • package?security;??
  • import?java.io.IOException;??
  • import?java.util.HashMap;??
  • import?java.util.List;??
  • import?java.util.Map;??
  • import?java.util.Set;??
  • ??
  • import?javax.annotation.PostConstruct;??
  • ??
  • import?org.slf4j.Logger;??
  • import?org.slf4j.LoggerFactory;??
  • import?org.springframework.beans.factory.annotation.Autowired;??
  • import?org.springframework.boot.SpringApplication;??
  • import?org.springframework.boot.autoconfigure.EnableAutoConfiguration;??
  • import?org.springframework.boot.autoconfigure.SpringBootApplication;??
  • import?org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;??
  • import?org.springframework.web.method.HandlerMethod;??
  • import?org.springframework.web.servlet.mvc.method.RequestMappingInfo;??
  • import?org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;??
  • import?security.entity.SysResource;??
  • import?security.service.SResourceService;??
  • import?csecurity.service.UserService;??
  • import?security.support.MySecurityFilter;??
  • ??
  • @SpringBootApplication??
  • @EnableAutoConfiguration(exclude?=?MyFilterSecurityInterceptor.class)?//注意??
  • public?class?MainApplication{??
  • ??????
  • ????@Autowired??
  • ????private?SResourceService?sresourceService;??
  • ??????
  • ????private?static?final?Logger?log?=?LoggerFactory.getLogger(MainApplication.class);??
  • ????@PostConstruct??
  • ?????public?void?initApplication()?throws?IOException?{??
  • ?????????log.info("Running?with?Spring?profile(s)?:?{}");???
  • ????}??
  • ???????
  • ????public?static?void?main(String[]?args)?{??
  • ????????//SpringApplication.run(MainApplication.class,?args);??
  • ????????SpringApplication?app=new?SpringApplication(MainApplication.class);???????
  • ????????Appctx.ctx=app.run(args);??
  • ????????/*UserService?suserService?=?(UserService)?Appctx.ctx.getBean("suserService");?
  • ????????SysUser?su=?suserService.findByName("user");?
  • ????????System.out.println("密碼"+su.getPassword());?
  • ????????System.out.println("名字"+su.getName());?
  • ????????BCryptPasswordEncoder?bc=new?BCryptPasswordEncoder(4);//將密碼加密?
  • ????????su.setPassword(bc.encode(su.getPassword()));?
  • ????????System.out.println("密碼"+su.getPassword());?
  • ????????suserService.update(su);*/??
  • }??
  • }??
  • package security; import java.io.IOException; import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Set;import javax.annotation.PostConstruct;import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; import org.springframework.web.method.HandlerMethod; import org.springframework.web.servlet.mvc.method.RequestMappingInfo; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; import security.entity.SysResource; import security.service.SResourceService; import csecurity.service.UserService; import security.support.MySecurityFilter;@SpringBootApplication @EnableAutoConfiguration(exclude = MyFilterSecurityInterceptor.class) //注意 public class MainApplication{@Autowiredprivate SResourceService sresourceService;private static final Logger log = LoggerFactory.getLogger(MainApplication.class);@PostConstructpublic void initApplication() throws IOException {log.info("Running with Spring profile(s) : {}"); }public static void main(String[] args) {//SpringApplication.run(MainApplication.class, args);SpringApplication app=new SpringApplication(MainApplication.class); Appctx.ctx=app.run(args);/*UserService suserService = (UserService) Appctx.ctx.getBean("suserService");SysUser su= suserService.findByName("user");System.out.println("密碼"+su.getPassword());System.out.println("名字"+su.getName());BCryptPasswordEncoder bc=new BCryptPasswordEncoder(4);//將密碼加密su.setPassword(bc.encode(su.getPassword()));System.out.println("密碼"+su.getPassword());suserService.update(su);*/ } }
    至此,我們spring security4就集成成功了,代碼,博主已經驗證,如有什么錯誤的地方,歡迎提出。謝謝!
    還有資源表中的url可以使用spring的RequestMappingHandlerMapping類自動掃描入庫,具體請見http://blog.csdn.net/code__code/article/details/53886912。

    總結

    以上是生活随笔為你收集整理的Spring boot+Spring Security 4配置整合实例的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。