本例所覆蓋的內容:
1.?使用Spring Security管理用戶身份認證、登錄退出
2.?用戶密碼加密及驗證
3.?采用數據庫的方式實現Spring Security的remember-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")??????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;????????????????????@Column(name="resourceId",length=50)??????????private?String?resourceId;????????????????????@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;?????????????????????@Column(name="resourceId",length=50)??????????private?String?resourceId;????????????????????@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;??????????????????????????????@Override??????protected?void?configure(HttpSecurity?http)?throws?Exception?{??????????http??????????.authorizeRequests()??????????.antMatchers("/home").permitAll()??????????.anyRequest().authenticated()???????????.antMatchers("/hello").hasAuthority("ADMIN")???????????.and()??????????.formLogin()??????????.loginPage("/login")??????????.permitAll()??????????.successHandler(loginSuccessHandler())???????????.and()??????????.logout()??????????.logoutSuccessUrl("/home")???????????.permitAll()??????????.invalidateHttpSession(true)??????????.and()??????????.rememberMe()??????????.tokenValiditySeconds(1209600);??????}????????@Autowired??????public?void?configureGlobal(AuthenticationManagerBuilder?auth)?throws?Exception?{?????????????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?user?=?userService.findByName(userName);??????????if?(user?==?null)?{??????????????throw?new?UsernameNotFoundException("UserName?"?+?userName?+?"?not?found");??????????}????????????????????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?{??????????????????????SysUser?userDetails?=?(SysUser)authentication.getPrincipal();???????????????????????????????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?app=new?SpringApplication(MainApplication.class);?????????????????????????Appctx.ctx=app.run(args);?????????????????????}??}??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?
????????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;?????????@Service??public?class?CustomInvocationSecurityMetadataSourceService?implements??????????FilterInvocationSecurityMetadataSource?{????????????@Autowired??????private?SResourceVODao?sResourceVODao;????????????@Autowired??????private?SRoleVODao?sRoleVODao;????????????private?static?Map<String,?Collection<ConfigAttribute>>?resourceMap?=?null;??????????????????@PostConstruct<span?style="color:#33cc00;">??????private?void?loadResourceDefine()?{??<span?style="color:#33cc00;">???????<span?style="color:#33cc00;">??????????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){????????????????????????????????????Object?value?=?sr.get("name");??????????????????String?name?=?String.valueOf(value);??????????????????query.add(name);??????????????}??????????}??????????<span?style="color:#33cc00;">???</span>??????????resourceMap?=?new?HashMap<String,?Collection<ConfigAttribute>>();????????????for?(String?auth?:?query)?{??????????????ConfigAttribute?ca?=?new?SecurityConfig(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;">???</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;">????????????@Override??????public?Collection<ConfigAttribute>?getAttributes(Object?object)??????????????throws?IllegalArgumentException?{??????????System.out.println("nwuidhwuiehdfu");??????????<span?style="color:#33cc00;">??????????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?
????????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;?????????????@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();?????????????}??????????????????????????????@Override??????protected?void?configure(HttpSecurity?http)?throws?Exception?{??????????http??????????.addFilterBefore(mySecurityFilter,?FilterSecurityInterceptor.class)??????????.authorizeRequests()??????????.antMatchers("/home").permitAll()??????????.anyRequest().authenticated()????????????????????.and()??????????.formLogin()??????????.loginPage("/login")??????????????.permitAll()??????????.successHandler(loginSuccessHandler())??????????.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?{?????????????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.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?app=new?SpringApplication(MainApplication.class);???????????????Appctx.ctx=app.run(args);???????????????????}??}??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配置整合实例的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。