Spring boot+Spring Security 4配置整合实例
本例所覆盖的内容:
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中加入如下片段:
- 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
- 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")//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 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;
}
}
- 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;
}
}
- 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表
- <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配置类,其中不明所以的地方请参照上面的图,慢慢往下看。
- 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 {
@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();
}
}
2、CustomUserDetailsService.java
- 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;@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;
}
}
3、SecurityUser.java
- 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());
}
}@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;
}
}
4、LoginSuccessHandler.java
- 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 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;
}
}
5、MvcConfig.java
- 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 {@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");
}
}
6、在resource下面创建templates目录,然后放相关的html文件:
home.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>
<!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
- <!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
- <!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
- 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
- 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 参照流程图
- /*
- * @(#) 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 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>();
}
// 根据URL,找到相关的权限配置。
@Override
public 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;
}
@Override
public boolean supports(Class<?> arg0) {
return true;
}
}
2、CustomAccessDecisionManager.java
- /*
- * @(#) 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(); <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>
}
}
3、 MyFilterSecurityInterceptor.java
- /*
- * @(#) 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 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===========================");
}
}
接下来修改一个类的 大家注意:
WebSecurityConfig.java
- 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 {@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();
}
}
ServletInitializer.java
- 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 {@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 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{@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);*/
}
}
至此,我们spring security4就集成成功了,代码,博主已经验证,如有什么错误的地方,欢迎提出。谢谢!
还有资源表中的url可以使用spring的RequestMappingHandlerMapping类自动扫描入库,具体请见http://blog.csdn.net/code__code/article/details/53886912。
Spring boot+Spring Security 4配置整合实例的更多相关文章
- Spring boot+Spring Security 4配置整合实例 【转】
http://blog.csdn.net/code__code/article/details/53885510
- [权限管理系统(四)]-spring boot +spring security短信认证+redis整合
[权限管理系统]spring boot +spring security短信认证+redis整合 现在主流的登录方式主要有 3 种:账号密码登录.短信验证码登录和第三方授权登录,前面一节Sprin ...
- Spring Boot 2.x 综合示例-整合thymeleaf、mybatis、shiro、logging、cache开发一个文章发布管理系统
一.概述 经过HelloWorld示例(Spring Boot 2.x 快速入门(上)HelloWorld示例)( Spring Boot 2.x 快速入门(下)HelloWorld示例详解)两篇的学 ...
- 快速搭建基于Spring Boot + Spring Security 环境
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 1.Spring Security 权限管理框架介绍 简介: Spring Security 提供了基于 ...
- 基于Spring Boot+Spring Security+JWT+Vue前后端分离的开源项目
一.前言 最近整合Spring Boot+Spring Security+JWT+Vue 完成了一套前后端分离的基础项目,这里把它开源出来分享给有需要的小伙伴们 功能很简单,单点登录,前后端动态权限配 ...
- Spring Boot 2.0 快速集成整合消息中间件 Kafka
欢迎关注个人微信公众号: 小哈学Java, 每日推送 Java 领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!! 个人网站: https://www.exception.site ...
- 4、Spring Boot 2.x 自动配置原理
1.4 Spring Boot 自动配置原理 简介 spring boot自动配置功能可以根据不同情况来决定spring配置应该用哪个,不应该用哪个,举个例子: Spring的JdbcTemplate ...
- 学记:为spring boot写一个自动配置
spring boot遵循"约定优于配置"的原则,使用annotation对一些常规的配置项做默认配置,减少或不使用xml配置,让你的项目快速运行起来.spring boot的神奇 ...
- Spring boot +Spring Security + Thymeleaf 认证失败返回错误信息
[Please make sure to select the branch corresponding to the version of Thymeleaf you are using] Stat ...
随机推荐
- UVA 11400 Lighting System Design 照明系统设计
首先是一个贪心,一种灯泡要么全都换,要么全都不换. 先排序,定义状态d[i]为前面i种灯泡的最小花费,状态转移就是从d[j],j<i,加上 i前面的j+1到i-1种灯泡换成i的花费. 下标排序玩 ...
- KissXML的XPath选取问题
XMPPFramework用的XML解析库还是大神自己写的KissXML,有些人生下来就是让人仰望的,哎. 进入主题,如下一段XML: <paramsxmlns="namespace& ...
- Catalan 数
概要 在一些面试的智力题中会遇到此数的变形,如果完全不了解,直接想结果是很困难的,故在此简单介绍一下. 基本定义 Catalan 数的定义根据不同的应用环境有很多不同的定义方式,下面给出一个. ...
- 苹果电脑macbook怎样强制关闭软件
尝试快捷键Command+Q 选择当前处于界面最前端的应用,同时按住Command+Q退出程序,并不代表强制退出应用,主要用于一些假死的应用. 2 通过快捷键Command+option+Shift+ ...
- Java产生GUID
/** * 产生GUID */public static final String generateGUID(){ UUID uuid = UUID.randomUUID(); return uuid ...
- 2017年网络空间安全技术大赛部分writeup
作为一个bin小子,这次一个bin都没做出来,我很羞愧. 0x00 拯救鲁班七号 具体操作不多说,直接进入反编译源码阶段 可以看到,只要2处的str等于a就可以了,而str是由1处的checkPass ...
- 如何查看 JAR 包的源代码
ava 项目的编译文件经常被打包成 JAR(Java Archive,Java 归档文件)文件,当然,作为学习,有时候也非常想看到这个 JAR 被打包前的源代码是怎么样的. 下面提供几种查看 JAR ...
- javaEE(7)_自定义标签&JSTL标签(JSP Standard Tag Library)
一.自定义标签简介 1.自定义标签主要用于移除Jsp页面中的java代码,jsp禁止出现一行java脚本. 2.使用自定义标签移除jsp页面中的java代码,只需要完成以下两个步骤: •编写一个实现T ...
- Java第十二次作业:什么是一维数组?什么是对象数组?吃金币游戏2.0版 新增炸弹功能 新增游戏倒计时功能 新增胜利失败检测功能 使用如鹏游戏引擎制作窗体 一维数组设置金币
什么是数组? 数组的定义:是用统一的名字代表这批数据,用序号来区分各个数据.数组是无序的数据元素按有序的下标组成的集合,分配固定空间大小的一种容器. 如何理解:其实就是一个同时放很多数据的变量. a= ...
- vue-router介绍及简单使用
一.vue-router介绍 vue-router是vue官方提供的一个路由框架,控制页面路由,使用较为方便. 1.路由模式 hash(浏览器环境默认值),使用 URL hash 值来作路由,支持所有 ...