本例所覆盖的内容:

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中加入如下片段:


  1. compile('org.springframework.boot:spring-boot-starter-data-jpa')
  2. compile("org.springframework.boot:spring-boot-starter-thymeleaf")
  3. compile("org.springframework.boot:spring-boot-starter-security")<u>
  4. testCompile("org.springframework.boot:spring-boot-starter-test")
  5. 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种方法:

  1. 一种是全部利用配置文件,将用户、权限、资源(url)硬编码在xml文件中;
  2. 二种是用户和权限用数据库存储,而资源(url)和权限的对应采用硬编码配置。
  3. 三种是细分角色和权限,并将用户、角色、权限和资源均采用数据库存储,并且自定义过滤器,代替原有的FilterSecurityInterceptor过滤器         并分别实现AccessDecisionManager、InvocationSecurityMetadataSourceService和UserDetailsService,并在配置文件中进行相应配置。
  4. 四是修改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个类来配置吧!

  1. 当然要现在application.properties配置文件中配置好数据库。
  2. 开始配置相关的实体类 SysUser.java  SRole.java  SysResource.java SysResourceRole.java
    1. package security.entity;
    2. import java.util.Date;
    3. import java.util.HashSet;
    4. import java.util.Set;
    5. import javax.persistence.Column;
    6. import javax.persistence.Entity;
    7. import javax.persistence.FetchType;
    8. import javax.persistence.GeneratedValue;
    9. import javax.persistence.GenerationType;
    10. import javax.persistence.Id;
    11. import javax.persistence.OneToMany;
    12. import javax.persistence.Table;
    13. import javax.persistence.Temporal;
    14. import javax.persistence.TemporalType;
    15. @Entity
    16. @Table(name = "s_user")//code11
    17. public class SysUser implements java.io.Serializable {
    18. @Id
    19. @GeneratedValue(strategy = GenerationType.IDENTITY)
    20. @Column(name = "id", unique = true, nullable = false)
    21. private Integer id;
    22. @Column(name = "name", length = 120)
    23. private String name; //用户名
    24. @Column(name = "email", length = 50)
    25. private String email;//用户邮箱
    26. @Column(name = "password", length = 120)
    27. private String password;//用户密码
    28. @Temporal(TemporalType.DATE)
    29. @Column(name = "dob", length = 10)
    30. private Date dob;//时间
    31. @OneToMany(fetch = FetchType.EAGER, mappedBy = "SUser")
    32. private Set<SysRole> SysRoles = new HashSet<SysRole>(0);// 所对应的角色集合
    33. public SysUser() {
    34. }
    35. public SysUser(String name, String email, String password, Date dob, Set<SysRole> SysRoles) {
    36. this.name = name;
    37. this.email = email;
    38. this.password = password;
    39. this.dob = dob;
    40. this.SysRoles = SysRoles;
    41. }
    42. public Integer getId() {
    43. return this.id;
    44. }
    45. public void setId(Integer id) {
    46. this.id = id;
    47. }
    48. public String getName() {
    49. return this.name;
    50. }
    51. public void setName(String name) {
    52. this.name = name;
    53. }
    54. public String getEmail() {
    55. return this.email;
    56. }
    57. public void setEmail(String email) {
    58. this.email = email;
    59. }
    60. public String getPassword() {
    61. return this.password;
    62. }
    63. public void setPassword(String password) {
    64. this.password = password;
    65. }
    66. public Date getDob() {
    67. return this.dob;
    68. }
    69. public void setDob(Date dob) {
    70. this.dob = dob;
    71. }
    72. @OneToMany(fetch = FetchType.EAGER, mappedBy = "SUser")
    73. public Set<SysRole> getSysRoles() {
    74. return this.SysRoles;
    75. }
    76. public void setSRoles(Set<SysRole> SysRoles) {
    77. this.SysRoles = SysRoles;
    78. }
    79. }
    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&lt;SysRole&gt; SysRoles = new HashSet&lt;SysRole&gt;(0);// 所对应的角色集合 public SysUser() {
    } public SysUser(String name, String email, String password, Date dob, Set&lt;SysRole&gt; 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&lt;SysRole&gt; getSysRoles() {
    return this.SysRoles;
    } public void setSRoles(Set&lt;SysRole&gt; SysRoles) {
    this.SysRoles = SysRoles;
    }

    }

    1. package security.entity;  
    2.   
    3. import java.util.Date;  
    4.   
    5. import javax.persistence.Column;  
    6. import javax.persistence.Entity;  
    7. import javax.persistence.FetchType;  
    8. import javax.persistence.GeneratedValue;  
    9. import javax.persistence.GenerationType;  
    10. import javax.persistence.Id;  
    11. import javax.persistence.JoinColumn;  
    12. import javax.persistence.ManyToOne;  
    13. import javax.persistence.Table;  
    14. //角色表  
    15. @Entity  
    16. @Table(name="s_role")  
    17. public class SysRole {  
    18.     @Id  
    19.     @GeneratedValue(strategy=GenerationType.IDENTITY)  
    20.     @Column (name="id",length=10)  
    21.     private int id;  
    22.       
    23.     @ManyToOne(fetch = FetchType.LAZY)  
    24.     @JoinColumn(name = "uid", nullable = false)  
    25.     private SysUser SUser;//角色对应的用户实体  
    26.       
    27.     @Column(name="name",length=100)  
    28.     private String name;//角色名称  
    29.       
    30.     public int getId() {  
    31.         return id;  
    32.     }  
    33.     public void setId(int id) {  
    34.         this.id = id;  
    35.     }  
    36.       
    37.     public String getName() {  
    38.         return name;  
    39.     }  
    40.     public void setName(String name) {  
    41.         this.name = name;  
    42.     }  
    43.     public SysUser getSUser() {  
    44.         return SUser;  
    45.     }  
    46.     public void setSUser(SysUser sUser) {  
    47.         SUser = sUser;  
    48.     }  
    49.       
    50.       
    51. }  
    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;
    }

    }

    1. package cn.paybay.ticketManager.entity;  
    2.   
    3. import javax.persistence.Column;  
    4. import javax.persistence.Entity;  
    5. import javax.persistence.GeneratedValue;  
    6. import javax.persistence.GenerationType;  
    7. import javax.persistence.Id;  
    8. import javax.persistence.Table;  
    9. @Entity  
    10. @Table(name="s_resource")  
    11. public class SysResource {  
    12.         @Id  
    13.         @GeneratedValue(strategy=GenerationType.IDENTITY)  
    14.         @Column (name="id",length=10)  
    15.         private int id;  
    16.           
    17.         @Column(name="resourceString",length=1000)  
    18.         private String resourceString;//url  
    19.           
    20.         @Column(name="resourceId",length=50)  
    21.         private String resourceId;//资源ID  
    22.           
    23.         @Column(name="remark",length=200)  
    24.         private String remark;//备注  
    25.           
    26.         @Column(name="resourceName",length=400)  
    27.         private String resourceName;//资源名称  
    28.           
    29.         @Column(name="methodName",length=400)  
    30.         private String methodName;//资源所对应的方法名  
    31.           
    32.         @Column(name="methodPath",length=1000)  
    33.         private String methodPath;//资源所对应的包路径  
    34.           
    35.         public int getId() {  
    36.             return id;  
    37.         }  
    38.   
    39.         public void setId(int id) {  
    40.             this.id = id;  
    41.         }  
    42.   
    43.         public String getResourceString() {  
    44.             return resourceString;  
    45.         }  
    46.   
    47.         public void setResourceString(String resourceString) {  
    48.             this.resourceString = resourceString;  
    49.         }  
    50.   
    51.         public String getResourceId() {  
    52.             return resourceId;  
    53.         }  
    54.   
    55.         public void setResourceId(String resourceId) {  
    56.             this.resourceId = resourceId;  
    57.         }  
    58.   
    59.         public String getRemark() {  
    60.             return remark;  
    61.         }  
    62.   
    63.         public void setRemark(String remark) {  
    64.             this.remark = remark;  
    65.         }  
    66.   
    67.         public String getResourceName() {  
    68.             return resourceName;  
    69.         }  
    70.   
    71.         public void setResourceName(String resourceName) {  
    72.             this.resourceName = resourceName;  
    73.         }  
    74.   
    75.         public String getMethodName() {  
    76.             return methodName;  
    77.         }  
    78.   
    79.         public void setMethodName(String methodName) {  
    80.             this.methodName = methodName;  
    81.         }  
    82.   
    83.         public String getMethodPath() {  
    84.             return methodPath;  
    85.         }  
    86.   
    87.         public void setMethodPath(String methodPath) {  
    88.             this.methodPath = methodPath;  
    89.         }  
    90.           
    91.           
    92. }  
    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;
    }

    }

    1. package security.entity;  
    2.   
    3. import java.util.Date;  
    4.   
    5. import javax.persistence.Column;  
    6. import javax.persistence.Entity;  
    7. import javax.persistence.FetchType;  
    8. import javax.persistence.GeneratedValue;  
    9. import javax.persistence.GenerationType;  
    10. import javax.persistence.Id;  
    11. import javax.persistence.JoinColumn;  
    12. import javax.persistence.ManyToOne;  
    13. import javax.persistence.Table;  
    14. @Entity  
    15. @Table(name="s_resource_role")  
    16. public class SysResourceRole {  
    17.         @Id  
    18.         @GeneratedValue(strategy=GenerationType.IDENTITY)  
    19.         @Column (name="id",length=10)  
    20.         private int id;  
    21.           
    22.         @Column(name="roleId",length=50)  
    23.         private String roleId; //角色ID  
    24.           
    25.         @Column(name="resourceId",length=50)  
    26.         private String resourceId;//资源ID  
    27.           
    28.         @Column(name="updateTime")  
    29.         private Date updateTime;//更新时间  
    30.   
    31.         public int getId() {  
    32.             return id;  
    33.         }  
    34.   
    35.         public void setId(int id) {  
    36.             this.id = id;  
    37.         }  
    38.   
    39.         public String getRoleId() {  
    40.             return roleId;  
    41.         }  
    42.   
    43.         public void setRoleId(String roleId) {  
    44.             this.roleId = roleId;  
    45.         }  
    46.   
    47.         public String getResourceId() {  
    48.             return resourceId;  
    49.         }  
    50.   
    51.         public void setResourceId(String resourceId) {  
    52.             this.resourceId = resourceId;  
    53.         }  
    54.   
    55.         public Date getUpdateTime() {  
    56.             return updateTime;  
    57.         }  
    58.   
    59.         public void setUpdateTime(Date updateTime) {  
    60.             this.updateTime = updateTime;  
    61.         }  
    62.   
    63.           
    64. }  
    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会自动创建表。在表中插入几条测试数据:

  3. s_user表
  4. s_role表



6.s_resource表

7.s_resource_role表

  1. <span style="color:rgb(51,204,0);">//请勿手工写入数据 供remember-me功能使用</span>
  2. CREATE TABLE `persistent_logins` (
  3. `username` varchar(64) NOT NULL,
  4. `series` varchar(64) NOT NULL,
  5. `token` varchar(64) NOT NULL,
  6. `last_used` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
  7. PRIMARY KEY (`series`)
  8. )
//请勿手工写入数据 供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配置类,其中不明所以的地方请参照上面的图,慢慢往下看。

  1. package security;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.context.annotation.Bean;
  4. import org.springframework.context.annotation.Configuration;
  5. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
  6. import org.springframework.security.config.annotation.web.builders.HttpSecurity;
  7. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
  8. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
  9. import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;
  10. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  11. import security.support.CustomUserDetailsService;
  12. import security.support.LoginSuccessHandler;
  13. @Configuration
  14. @EnableWebSecurity
  15. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
  16. @Autowired
  17. private CustomUserDetailsService customUserDetailsService;
  18. //http://localhost:8080/login 输入正确的用户名密码 并且选中remember-me 则登陆成功,转到 index页面
  19. //再次访问index页面无需登录直接访问
  20. //访问http://localhost:8080/home 不拦截,直接访问,
  21. //访问http://localhost:8080/hello 需要登录验证后,且具备 “ADMIN”权限hasAuthority("ADMIN")才可以访问
  22. @Override
  23. protected void configure(HttpSecurity http) throws Exception {
  24. http
  25. .authorizeRequests()
  26. .antMatchers("/home").permitAll()//访问:/home 无需登录认证权限
  27. .anyRequest().authenticated() //其他所有资源都需要认证,登陆后访问
  28. .antMatchers("/hello").hasAuthority("ADMIN") //登陆后之后拥有“ADMIN”权限才可以访问/hello方法,否则系统会出现“403”权限不足的提示
  29. .and()
  30. .formLogin()
  31. .loginPage("/login")//指定登录页是”/login”
  32. .permitAll()
  33. .successHandler(loginSuccessHandler()) //登录成功后可使用loginSuccessHandler()存储用户信息,可选。
  34. .and()
  35. .logout()
  36. .logoutSuccessUrl("/home") //退出登录后的默认网址是”/home”
  37. .permitAll()
  38. .invalidateHttpSession(true)
  39. .and()
  40. .rememberMe()//登录后记住用户,下次自动登录,数据库中必须存在名为persistent_logins的表
  41. .tokenValiditySeconds(1209600);
  42. }
  43. @Autowired
  44. public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
  45. //指定密码加密所使用的加密器为passwordEncoder()
  46. //需要将密码加密后写入数据库
  47. auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());
  48. auth.eraseCredentials(false);
  49. }
  50. @Bean
  51. public BCryptPasswordEncoder passwordEncoder() {
  52. return new BCryptPasswordEncoder(4);
  53. }
  54. @Bean
  55. public LoginSuccessHandler loginSuccessHandler(){
  56. return new LoginSuccessHandler();
  57. }
  58. }
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

  1. package security.support;
  2. import org.springframework.beans.factory.annotation.Autowired;
  3. import org.springframework.security.core.userdetails.UserDetails;
  4. import org.springframework.security.core.userdetails.UserDetailsService;
  5. import org.springframework.security.core.userdetails.UsernameNotFoundException;
  6. import org.springframework.stereotype.Component;
  7. import security.entity.SysUser;
  8. import security.entity.User;
  9. import security.service.UserService;
  10. @Component
  11. public class CustomUserDetailsService implements UserDetailsService {
  12. @Autowired  //业务服务类
  13. private UserService userService;
  14. @Override
  15. public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
  16. //SysUser对应数据库中的用户表,是最终存储用户和密码的表,可自定义
  17. //本例使用SysUser中的name作为用户名:
  18. SysUser user = userService.findByName(userName);
  19. if (user == null) {
  20. throw new UsernameNotFoundException("UserName " + userName + " not found");
  21. }
  22. // SecurityUser实现UserDetails并将SysUser的name映射为username
  23. SecurityUser seu = new SecurityUser(user);
  24. return  seu;
  25. }
  26. }
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

  1. package security.support;
  2. import java.util.ArrayList;
  3. import java.util.Collection;
  4. import java.util.HashSet;
  5. import java.util.List;
  6. import java.util.Set;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.security.core.GrantedAuthority;
  9. import org.springframework.security.core.authority.SimpleGrantedAuthority;
  10. import org.springframework.security.core.userdetails.UserDetails;
  11. import security.entity.SysRole<span style="font-family:Arial, Helvetica, sans-serif;">;</span>
  12. import security.entity.SysUser;
  13. public class SecurityUser extends SysUser implements UserDetails {
  14. private static final long serialVersionUID = 1L;
  15. public SecurityUser(SysUser suser) {
  16. if(suser != null)
  17. {
  18. this.setId(suser.getId());
  19. this.setName(suser.getName());
  20. this.setEmail(suser.getEmail());
  21. this.setPassword(suser.getPassword());
  22. this.setDob(suser.getDob());
  23. this.setSysRoles(suser.getSysRoles());
  24. }
  25. }
  26. @Override
  27. public Collection<? extends GrantedAuthority> getAuthorities() {
  28. Collection<GrantedAuthority> authorities = new ArrayList<>();
  29. Set<SysRole> userRoles = this.getSysRoles();
  30. if(userRoles != null)
  31. {
  32. for (SysRole role : userRoles) {
  33. SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role.getName());
  34. authorities.add(authority);
  35. }
  36. }
  37. return authorities;
  38. }
  39. @Override
  40. public String getPassword() {
  41. return super.getPassword();
  42. }
  43. @Override
  44. public String getUsername() {
  45. return super.getName();
  46. }
  47. @Override
  48. public boolean isAccountNonExpired() {
  49. return true;
  50. }
  51. @Override
  52. public boolean isAccountNonLocked() {
  53. return true;
  54. }
  55. @Override
  56. public boolean isCredentialsNonExpired() {
  57. return true;
  58. }
  59. @Override
  60. public boolean isEnabled() {
  61. return true;
  62. }
  63. }
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&lt;? extends GrantedAuthority&gt; getAuthorities() { Collection&lt;GrantedAuthority&gt; authorities = new ArrayList&lt;&gt;();
Set&lt;SysRole&gt; 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

  1. package security.support;
  2. import java.io.IOException;
  3. import java.util.Set;
  4. import javax.servlet.ServletException;
  5. import javax.servlet.http.HttpServletRequest;
  6. import javax.servlet.http.HttpServletResponse;
  7. import org.springframework.security.core.Authentication;
  8. import org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler;
  9. import security.entity.SysRole;
  10. import security.entity.SysUser;
  11. public class LoginSuccessHandler extends
  12. SavedRequestAwareAuthenticationSuccessHandler {
  13. @Override
  14. public void onAuthenticationSuccess(HttpServletRequest request,
  15. HttpServletResponse response, Authentication authentication) throws IOException,
  16. ServletException {
  17. //获得授权后可得到用户信息   可使用SUserService进行数据库操作
  18. SysUser userDetails = (SysUser)authentication.getPrincipal();
  19. /* Set<SysRole> roles = userDetails.getSysRoles();*/
  20. //输出登录提示信息
  21. System.out.println("管理员 " + userDetails.getName() + " 登录");
  22. System.out.println("IP :"+getIpAddress(request));
  23. super.onAuthenticationSuccess(request, response, authentication);
  24. }
  25. public String getIpAddress(HttpServletRequest request){
  26. String ip = request.getHeader("x-forwarded-for");
  27. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  28. ip = request.getHeader("Proxy-Client-IP");
  29. }
  30. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  31. ip = request.getHeader("WL-Proxy-Client-IP");
  32. }
  33. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  34. ip = request.getHeader("HTTP_CLIENT_IP");
  35. }
  36. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  37. ip = request.getHeader("HTTP_X_FORWARDED_FOR");
  38. }
  39. if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
  40. ip = request.getRemoteAddr();
  41. }
  42. return ip;
  43. }
  44. }
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

  1. package security;
  2. import org.springframework.context.annotation.Configuration;
  3. import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
  4. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  5. @Configuration
  6. public class MvcConfig extends WebMvcConfigurerAdapter {
  7. @Override
  8. public void addViewControllers(ViewControllerRegistry registry) {
  9. registry.addViewController("/home").setViewName("home");
  10. registry.addViewController("/").setViewName("home");
  11. registry.addViewController("/hello").setViewName("hello");
  12. registry.addViewController("/login").setViewName("login");
  13. }
  14. }
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

  1. <!DOCTYPE html>
  2. <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">
  3. <head>
  4. <title>Spring Security Example</title>
  5. </head>
  6. <body>
  7. <h1>Welcome!</h1>
  8. <p>Click <a th:href="@{/hello}">here</a> to see a greeting.</p>
  9. </body>
  10. </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>
    &lt;p&gt;Click &lt;a th:href="@{/hello}"&gt;here&lt;/a&gt; to see a greeting.&lt;/p&gt;
&lt;/body&gt;

</html>

hello.html

  1. <!DOCTYPE html>  
  2. <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"  
  3.       xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">  
  4.     <head>  
  5.         <title>Hello World!</title>  
  6.     </head>  
  7.     <body>  
  8.         <h1 th:inline="text">Hello [[${#httpServletRequest.remoteUser}]]!</h1>  
  9.         <form th:action="@{/logout}" method="post">  
  10.             <input type="submit" value="Sign Out"/>  
  11.         </form>  
  12.     </body>  
  13. </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

  1. <!DOCTYPE html>  
  2. <html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="http://www.thymeleaf.org"  
  3.       xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity3">  
  4.     <head>  
  5.         <title>Spring Security Example </title>  
  6.     </head>  
  7.     <body>  
  8.         <div th:if="${param.error}">  
  9.             Invalid username and password.  
  10.         </div>  
  11.         <div th:if="${param.logout}">  
  12.             You have been logged out.  
  13.         </div>  
  14.         <form th:action="@{/login}" method="post">  
  15.             <div><label> User Name : <input type="text" name="username"/> </label></div>  
  16.             <div><label> Password: <input type="password" name="password"/> </label></div>  
  17.             <div><input type="submit" value="Sign In"/></div>  
  18.             <input type="checkbox" name="remember-me" value="true" th:checked="checked"/><p>Remember me</p>  
  19.         </form>  
  20.     </body>  
  21. </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

  1. package security;
  2. import org.springframework.boot.SpringApplication;
  3. import org.springframework.boot.autoconfigure.SpringBootApplication;
  4. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
  5. import org.springframework.web.servlet.config.annotation.ViewControllerRegistry;
  6. import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter;
  7. import security.entity.SysUser;
  8. import security.entity.User;
  9. import security.service.UserService;
  10. import security.Appctx;
  11. @SpringBootApplication
  12. public class MainApplication{
  13. public static void main(String[] args) {
  14. //SpringApplication.run(MainApplication.class, args);
  15. SpringApplication app=new SpringApplication(MainApplication.class);
  16. Appctx.ctx=app.run(args);
  17. /*UserService suserService = (UserService) Appctx.ctx.getBean("suserService");
  18. SysUser su= suserService.findByName("TEST");
  19. BCryptPasswordEncoder bc=new BCryptPasswordEncoder(4);//将密码加密 可以先设置初始密码:000000
  20. su.setPassword(bc.encode(su.getPassword()));//然后使用密码为key值进行加密,运行主类后,会自动加密密码,可连接数据库查看。
  21. System.out.println("密码"+su.getPassword());
  22. suserService.update(su);//运行一次后记得注释这段重复加密会无法匹配*/
  23. }
  24. }
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

  1. package security.support;
  2. import org.springframework.context.ApplicationContext;
  3. public class Appctx {
  4. public static ApplicationContext ctx=null;
  5. public static Object getObject(String string){
  6. return ctx.getBean(string);
  7. }
  8. }
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 参照流程图

  1. /*
  2. * @(#) MyInvocationSecurityMetadataSourceService.java  2011-3-23 下午02:58:29
  3. *
  4. * Copyright 2011 by Sparta
  5. */
  6. package security.support;
  7. import java.util.ArrayList;
  8. import java.util.Collection;
  9. import java.util.HashMap;
  10. import java.util.Iterator;
  11. import java.util.List;
  12. import java.util.Map;
  13. import java.util.Map.Entry;
  14. import java.util.Set;
  15. import javax.annotation.PostConstruct;
  16. import org.hibernate.Session;
  17. import org.hibernate.SessionFactory;
  18. import org.springframework.beans.factory.annotation.Autowired;
  19. import org.springframework.context.ApplicationContext;
  20. import org.springframework.context.support.ClassPathXmlApplicationContext;
  21. import org.springframework.security.access.ConfigAttribute;
  22. import org.springframework.security.access.SecurityConfig;
  23. import org.springframework.security.core.GrantedAuthority;
  24. import org.springframework.security.core.context.SecurityContextHolder;
  25. import org.springframework.security.core.userdetails.UserDetails;
  26. import org.springframework.security.web.FilterInvocation;
  27. import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
  28. import org.springframework.security.web.util.matcher.AntPathRequestMatcher;
  29. import org.springframework.security.web.util.matcher.RequestMatcher;
  30. import org.springframework.stereotype.Component;
  31. import org.springframework.stereotype.Service;
  32. import security.dao.SResourceVODao;
  33. import security.dao.SRoleDao;
  34. import security.dao.SRoleVODao;
  35. import security.entity.SRole;
  36. import security.service.SResourceService;
  37. import security.service.SRoleService;
  38. /**
  39. * 最核心的地方,就是提供某个资源对应的权限定义,即getAttributes方法返回的结果。 此类在初始化时,应该取到所有资源及其对应角色的定义。
  40. *
  41. */
  42. @Service
  43. public class CustomInvocationSecurityMetadataSourceService implements
  44. FilterInvocationSecurityMetadataSource {
  45. @Autowired
  46. private SResourceVODao sResourceVODao;
  47. @Autowired
  48. private SRoleVODao sRoleVODao;
  49. private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
  50. /*public CustomInvocationSecurityMetadataSourceService(SResourceService sres,SRoleService sR) {
  51. this.sResourceService = sres;
  52. this.sRoleService = sR;
  53. loadResourceDefine();
  54. }*/
  55. @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>
  56. private void loadResourceDefine() {  <span style="color:#33cc00;"> //一定要加上<span style="font-family:Arial, Helvetica, sans-serif;">@PostConstruct注解</span></span>
  57. <span style="color:#33cc00;">// 在Web服务器启动时,提取系统中的所有权限。</span>
  58. List<Map<String,Object>> list =sRoleVODao.findAll();
  59. List<String> query = new ArrayList<String>();
  60. if(list!=null && list.size()>0) {
  61. for(Map<String,Object> sr :list){
  62. //String name = sr.get("name")
  63. Object value = sr.get("name");
  64. String name = String.valueOf(value);
  65. query.add(name);
  66. }
  67. }
  68. <span style="color:#33cc00;">/*
  69. * 应当是资源为key, 权限为value。 资源通常为url, 权限就是那些以ROLE_为前缀的角色。 一个资源可以由多个权限来访问。
  70. * sparta
  71. */</span>
  72. resourceMap = new HashMap<String, Collection<ConfigAttribute>>();
  73. for (String auth : query) {
  74. ConfigAttribute ca = new SecurityConfig(auth);
  75. //List<Map<String,Object>> query1 = sResourceVODao.findByRoleName(auth);
  76. List<String> query1 = new ArrayList<String>();
  77. List<Map<String, Object>>  list1 = sResourceVODao.findByRoleName(auth);
  78. if(list1!=null && list1.size()>0) {
  79. for(Map<String, Object> map :list1){
  80. Object value = map.get("resource_string");
  81. String url = String.valueOf(value);
  82. query1.add(url);
  83. }
  84. }
  85. for (String res : query1) {
  86. String url = res;
  87. <span style="color:#33cc00;">/*
  88. * 判断资源文件和权限的对应关系,如果已经存在相关的资源url,则要通过该url为key提取出权限集合,将权限增加到权限集合中。
  89. * sparta
  90. */</span>
  91. if (resourceMap.containsKey(url)) {
  92. Collection<ConfigAttribute> value = resourceMap.get(url);
  93. value.add(ca);
  94. resourceMap.put(url, value);
  95. } else {
  96. Collection<ConfigAttribute> atts = new ArrayList<ConfigAttribute>();
  97. atts.add(ca);
  98. resourceMap.put(url, atts);
  99. }
  100. }
  101. }
  102. }
  103. @Override
  104. public Collection<ConfigAttribute> getAllConfigAttributes() {
  105. return new ArrayList<ConfigAttribute>();
  106. }
  107. <span style="color:#33cc00;">
  108. // 根据URL,找到相关的权限配置。</span>
  109. @Override
  110. public Collection<ConfigAttribute> getAttributes(Object object)
  111. throws IllegalArgumentException {
  112. System.out.println("nwuidhwuiehdfu");
  113. <span style="color:#33cc00;">// object 是一个URL,被用户请求的url。</span>
  114. FilterInvocation filterInvocation = (FilterInvocation) object;
  115. if (resourceMap == null) {
  116. loadResourceDefine();
  117. }
  118. Iterator<String> ite = resourceMap.keySet().iterator();
  119. while (ite.hasNext()) {
  120. String resURL = ite.next();
  121. RequestMatcher requestMatcher = new AntPathRequestMatcher(resURL);
  122. if(requestMatcher.matches(filterInvocation.getHttpRequest())) {
  123. return resourceMap.get(resURL);
  124. }
  125. }
  126. return null;
  127. }
  128. @Override
  129. public boolean supports(Class<?> arg0) {
  130. return true;
  131. }
  132. }
/*
* @(#) 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&lt;String, Collection&lt;ConfigAttribute&gt;&gt; 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;">&nbsp; </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&lt;Map&lt;String,Object&gt;&gt; list =sRoleVODao.findAll();
List&lt;String&gt; query = new ArrayList&lt;String&gt;();
if(list!=null &amp;&amp; list.size()&gt;0) {
for(Map&lt;String,Object&gt; 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&lt;String, Collection&lt;ConfigAttribute&gt;&gt;(); for (String auth : query) {
ConfigAttribute ca = new SecurityConfig(auth);
//List&lt;Map&lt;String,Object&gt;&gt; query1 = sResourceVODao.findByRoleName(auth);
List&lt;String&gt; query1 = new ArrayList&lt;String&gt;();
List&lt;Map&lt;String, Object&gt;&gt; list1 = sResourceVODao.findByRoleName(auth);
if(list1!=null &amp;&amp; list1.size()&gt;0) {
for(Map&lt;String, Object&gt; 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&lt;ConfigAttribute&gt; value = resourceMap.get(url);
value.add(ca);
resourceMap.put(url, value);
} else {
Collection&lt;ConfigAttribute&gt; atts = new ArrayList&lt;ConfigAttribute&gt;();
atts.add(ca);
resourceMap.put(url, atts);
} }
} } @Override
public Collection&lt;ConfigAttribute&gt; getAllConfigAttributes() {
return new ArrayList&lt;ConfigAttribute&gt;();
}

// 根据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&lt;?&gt; arg0) { return true;
}

}

2、CustomAccessDecisionManager.java

  1. /*
  2. * @(#) MyAccessDecisionManager.java  2011-3-23 下午04:41:12
  3. *
  4. * Copyright 2011 by Sparta
  5. */
  6. package security.support;
  7. import java.util.Collection;
  8. import java.util.Iterator;
  9. import org.springframework.security.access.AccessDecisionManager;
  10. import org.springframework.security.access.AccessDeniedException;
  11. import org.springframework.security.access.ConfigAttribute;
  12. import org.springframework.security.access.SecurityConfig;
  13. import org.springframework.security.authentication.InsufficientAuthenticationException;
  14. import org.springframework.security.core.Authentication;
  15. import org.springframework.security.core.GrantedAuthority;
  16. import org.springframework.stereotype.Component;
  17. import org.springframework.stereotype.Service;
  18. <span style="color:#33cc00;">/**
  19. *AccessdecisionManager在Spring security中是很重要的。
  20. *
  21. *在验证部分简略提过了,所有的Authentication实现需要保存在一个GrantedAuthority对象数组中。
  22. *这就是赋予给主体的权限。 GrantedAuthority对象通过AuthenticationManager
  23. *保存到 Authentication对象里,然后从AccessDecisionManager读出来,进行授权判断。
  24. *
  25. *Spring Security提供了一些拦截器,来控制对安全对象的访问权限,例如方法调用或web请求。
  26. *一个是否允许执行调用的预调用决定,是由AccessDecisionManager实现的。
  27. *这个 AccessDecisionManager 被AbstractSecurityInterceptor调用,
  28. *它用来作最终访问控制的决定。 这个AccessDecisionManager接口包含三个方法:
  29. *
  30. void decide(Authentication authentication, Object secureObject,
  31. List<ConfigAttributeDefinition> config) throws AccessDeniedException;
  32. boolean supports(ConfigAttribute attribute);
  33. boolean supports(Class clazz);
  34. 从第一个方法可以看出来,AccessDecisionManager使用方法参数传递所有信息,这好像在认证评估时进行决定。
  35. 特别是,在真实的安全方法期望调用的时候,传递安全Object启用那些参数。
  36. 比如,让我们假设安全对象是一个MethodInvocation。
  37. 很容易为任何Customer参数查询MethodInvocation,
  38. 然后在AccessDecisionManager里实现一些有序的安全逻辑,来确认主体是否允许在那个客户上操作。
  39. 如果访问被拒绝,实现将抛出一个AccessDeniedException异常。
  40. 这个 supports(ConfigAttribute) 方法在启动的时候被
  41. AbstractSecurityInterceptor调用,来决定AccessDecisionManager
  42. 是否可以执行传递ConfigAttribute。
  43. supports(Class)方法被安全拦截器实现调用,
  44. 包含安全拦截器将显示的AccessDecisionManager支持安全对象的类型。
  45. */</span>
  46. @Service
  47. public class CustomAccessDecisionManager implements AccessDecisionManager {
  48. public void decide( Authentication authentication, Object object,
  49. Collection<ConfigAttribute> configAttributes)
  50. throws AccessDeniedException, InsufficientAuthenticationException{
  51. if( configAttributes == null ) {
  52. return ;
  53. }
  54. Iterator<ConfigAttribute> ite = configAttributes.iterator();
  55. while( ite.hasNext()){
  56. ConfigAttribute ca = ite.next();
  57. String needRole = ((SecurityConfig)ca).getAttribute();
  58. <span style="color:#33cc00;">   //ga 为用户所被赋予的权限。 needRole 为访问相应的资源应该具有的权限。</span>
  59. for( GrantedAuthority ga: authentication.getAuthorities()){
  60. if(needRole.trim().equals(ga.getAuthority().trim())){
  61. return;
  62. }
  63. }
  64. }
  65. throw new AccessDeniedException("权限不足");
  66. }
  67. public boolean supports( ConfigAttribute attribute ){
  68. <span style="color:#ff0000;">return true;</span><span style="color:#33cc00;">//都要设为true</span>
  69. }
  70. public boolean supports(Class<?> clazz){
  71. <span style="color:#ff0000;">return true;</span><span style="color:rgb(51,204,0);font-family:Arial, Helvetica, sans-serif;">//都要设为true</span>
  72. }
  73. }
/*
* @(#) 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&lt;ConfigAttribute&gt; configAttributes)
throws AccessDeniedException, InsufficientAuthenticationException{
if( configAttributes == null ) {
return ;
} Iterator&lt;ConfigAttribute&gt; 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&lt;?&gt; 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

  1. /*
  2. * @(#) MyFilterSecurityInterceptor.java  2011-3-23 上午07:53:03
  3. *
  4. * Copyright 2011 by Sparta
  5. */
  6. package security.support;
  7. import java.io.IOException;
  8. import java.util.Collection;
  9. import java.util.Map;
  10. import javax.annotation.PostConstruct;
  11. import javax.servlet.Filter;
  12. import javax.servlet.FilterChain;
  13. import javax.servlet.FilterConfig;
  14. import javax.servlet.ServletException;
  15. import javax.servlet.ServletRequest;
  16. import javax.servlet.ServletResponse;
  17. import org.springframework.beans.factory.annotation.Autowired;
  18. import org.springframework.security.access.ConfigAttribute;
  19. import org.springframework.security.access.SecurityMetadataSource;
  20. import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
  21. import org.springframework.security.access.intercept.InterceptorStatusToken;
  22. import org.springframework.security.authentication.AuthenticationManager;
  23. import org.springframework.security.web.FilterInvocation;
  24. import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
  25. import security.service.SResourceService;
  26. /**
  27. * 该过滤器的主要作用就是通过spring著名的IoC生成securityMetadataSource。
  28. * securityMetadataSource相当于本包中自定义的MyInvocationSecurityMetadataSourceService。
  29. * 该MyInvocationSecurityMetadataSourceService的作用提从数据库提取权限和资源,装配到HashMap中,
  30. * 供Spring Security使用,用于权限校验。
  31. * @author sparta 11/3/29
  32. *
  33. */
  34. @Component
  35. public class MySecurityFilter
  36. extends AbstractSecurityInterceptor
  37. implements Filter{
  38. @Autowired
  39. private CustomInvocationSecurityMetadataSourceService  mySecurityMetadataSource;
  40. @Autowired
  41. private CustomAccessDecisionManager myAccessDecisionManager;
  42. @Autowired
  43. private AuthenticationManager authenticationManager;
  44. @PostConstruct
  45. public void init(){
  46. super.setAuthenticationManager(authenticationManager);
  47. super.setAccessDecisionManager(myAccessDecisionManager);
  48. }
  49. public void doFilter( ServletRequest request, ServletResponse response, FilterChain chain)
  50. throws IOException, ServletException{
  51. FilterInvocation fi = new FilterInvocation( request, response, chain );
  52. invoke(fi);
  53. }
  54. public Class<? extends Object> getSecureObjectClass(){
  55. return FilterInvocation.class;
  56. }
  57. public void invoke( FilterInvocation fi ) throws IOException, ServletException{
  58. System.out.println("filter..........................");
  59. InterceptorStatusToken  token = super.beforeInvocation(fi);
  60. try{
  61. fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
  62. }finally{
  63. super.afterInvocation(token, null);
  64. }
  65. }
  66. @Override
  67. public SecurityMetadataSource obtainSecurityMetadataSource(){
  68. System.out.println("filtergergetghrthetyetyetyetyj");
  69. return this.mySecurityMetadataSource;
  70. }
  71. public void destroy(){
  72. System.out.println("filter===========================end");
  73. }
  74. public void init( FilterConfig filterconfig ) throws ServletException{
  75. System.out.println("filter===========================");
  76. }
  77. }
/*
* @(#) 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&lt;? extends Object&gt; 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

  1. package security;  
  2.   
  3. import org.springframework.beans.factory.annotation.Autowired;  
  4. import org.springframework.boot.autoconfigure.security.SecurityProperties;  
  5. import org.springframework.boot.web.servlet.FilterRegistrationBean;  
  6. import org.springframework.context.annotation.Bean;  
  7. import org.springframework.context.annotation.Configuration;  
  8. import org.springframework.core.annotation.Order;  
  9. import org.springframework.security.authentication.AuthenticationManager;  
  10. import org.springframework.security.authentication.AuthenticationProvider;  
  11. import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;  
  12. import org.springframework.security.config.annotation.web.builders.HttpSecurity;  
  13. import org.springframework.security.config.annotation.web.builders.WebSecurity;  
  14. import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;  
  15. import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;  
  16. import org.springframework.security.config.annotation.web.servlet.configuration.EnableWebMvcSecurity;  
  17. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;  
  18. import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;  
  19.   
  20. import security.support.CustomUserDetailsService;  
  21. import security.support.LoginSuccessHandler;  
  22. import security.support.MySecurityFilter;  
  23. @Configuration  
  24. @EnableWebSecurity  
  25. public class WebSecurityConfig extends WebSecurityConfigurerAdapter {  
  26.       
  27.     @Autowired  
  28.     private MyFilterSecurityInterceptor mySecurityFilter;  
  29.       
  30.     @Autowired  
  31.     private CustomUserDetailsService customUserDetailsService;  
  32.       
  33.     @Override  
  34.     public AuthenticationManager authenticationManagerBean() throws Exception {  
  35.        
  36.     return super.authenticationManagerBean();  
  37.        
  38.     }  
  39.     //http://localhost:8080/login 输入正确的用户名密码 并且选中remember-me 则登陆成功,转到 index页面   
  40.     //再次访问index页面无需登录直接访问  
  41.     //访问http://localhost:8080/home 不拦截,直接访问,  
  42.     //访问http://localhost:8080/hello 需要登录验证后,且具备 “ADMIN”权限hasAuthority("ADMIN")才可以访问  
  43.     @Override  
  44.     protected void configure(HttpSecurity http) throws Exception {  
  45.         http  
  46.         .addFilterBefore(mySecurityFilter, FilterSecurityInterceptor.class)//在正确的位置添加我们自定义的过滤器  
  47.         .authorizeRequests()  
  48.         .antMatchers("/home").permitAll()  
  49.         .anyRequest().authenticated()  
  50.         //.antMatchers("/hello").hasAuthority("ADMIN")  
  51.         .and()  
  52.         .formLogin()  
  53.         .loginPage("/login")      
  54.         .permitAll()  
  55.         .successHandler(loginSuccessHandler())//code3  
  56.         .and()  
  57.         .logout()  
  58.         .logoutSuccessUrl("/home")  
  59.         .permitAll()  
  60.         .invalidateHttpSession(true)  
  61.         .and()  
  62.         .rememberMe()  
  63.         .tokenValiditySeconds(1209600);  
  64.     }  
  65.     @Override  
  66.         public void configure(WebSecurity web) throws Exception {  
  67.             super.configure(web);  
  68.     }  
  69.     @Autowired  
  70.     public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {     
  71. //指定密码加密所使用的加密器为passwordEncoder()  
  72. //需要将密码加密后写入数据库   
  73.     auth.userDetailsService(customUserDetailsService).passwordEncoder(passwordEncoder());  
  74. //不删除凭据,以便记住用户  
  75.         auth.eraseCredentials(false);         
  76.     }  
  77.       
  78.     // Code5----------------------------------------------  
  79.     @Bean  
  80.     public BCryptPasswordEncoder passwordEncoder() {  
  81.         return new BCryptPasswordEncoder(4);  
  82.     }  
  83.   
  84.     // Code3----------------------------------------------  
  85.     @Bean  
  86.     public LoginSuccessHandler loginSuccessHandler(){  
  87.         return new LoginSuccessHandler();  
  88.     }  
  89. }  
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

  1. package security;  
  2.   
  3. import javax.servlet.FilterRegistration;  
  4. import javax.servlet.ServletContext;  
  5. import javax.servlet.ServletException;  
  6.   
  7. import org.springframework.boot.builder.SpringApplicationBuilder;  
  8. import org.springframework.boot.web.support.SpringBootServletInitializer;  
  9. import org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter;  
  10.   
  11. public class ServletInitializer extends SpringBootServletInitializer {  
  12.   
  13.     @Override  
  14.     protected SpringApplicationBuilder configure(SpringApplicationBuilder application) {  
  15.         return application.sources(MainApplication.class);  
  16.     }  
  17.       
  18.     @Override  
  19.     public void onStartup(ServletContext servletContext)  
  20.     throws ServletException {  
  21.      FilterRegistration.Dynamic openEntityManagerInViewFilter = servletContext.addFilter("openEntityManagerInViewFilter", OpenEntityManagerInViewFilter.class);  
  22.          openEntityManagerInViewFilter.setInitParameter("entityManagerFactoryBeanName","entityManagerFactory");  
  23.          openEntityManagerInViewFilter.addMappingForUrlPatterns(null, false, "/*");  
  24.     super.onStartup(servletContext);  
  25.     }  
  26. }  
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);
}

}

还有主类需要修改

  1. package security;  
  2. import java.io.IOException;  
  3. import java.util.HashMap;  
  4. import java.util.List;  
  5. import java.util.Map;  
  6. import java.util.Set;  
  7.   
  8. import javax.annotation.PostConstruct;  
  9.   
  10. import org.slf4j.Logger;  
  11. import org.slf4j.LoggerFactory;  
  12. import org.springframework.beans.factory.annotation.Autowired;  
  13. import org.springframework.boot.SpringApplication;  
  14. import org.springframework.boot.autoconfigure.EnableAutoConfiguration;  
  15. import org.springframework.boot.autoconfigure.SpringBootApplication;  
  16. import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;  
  17. import org.springframework.web.method.HandlerMethod;  
  18. import org.springframework.web.servlet.mvc.method.RequestMappingInfo;  
  19. import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;  
  20. import security.entity.SysResource;  
  21. import security.service.SResourceService;  
  22. import csecurity.service.UserService;  
  23. import security.support.MySecurityFilter;  
  24.   
  25. @SpringBootApplication  
  26. @EnableAutoConfiguration(exclude = MyFilterSecurityInterceptor.class) //注意  
  27. public class MainApplication{  
  28.       
  29.     @Autowired  
  30.     private SResourceService sresourceService;  
  31.       
  32.     private static final Logger log = LoggerFactory.getLogger(MainApplication.class);  
  33.     @PostConstruct  
  34.      public void initApplication() throws IOException {  
  35.          log.info("Running with Spring profile(s) : {}");   
  36.     }  
  37.        
  38.     public static void main(String[] args) {  
  39.         //SpringApplication.run(MainApplication.class, args);  
  40.         SpringApplication app=new SpringApplication(MainApplication.class);       
  41.         Appctx.ctx=app.run(args);  
  42.         /UserService suserService = (UserService) Appctx.ctx.getBean("suserService"); 
  43.         SysUser su= suserService.findByName("user"); 
  44.         System.out.println("密码"+su.getPassword()); 
  45.         System.out.println("名字"+su.getName()); 
  46.         BCryptPasswordEncoder bc=new BCryptPasswordEncoder(4);//将密码加密 
  47.         su.setPassword(bc.encode(su.getPassword())); 
  48.         System.out.println("密码"+su.getPassword()); 
  49.         suserService.update(su);/  
  50. }  
  51. }  
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配置整合实例的更多相关文章

  1. Spring boot+Spring Security 4配置整合实例 【转】

    http://blog.csdn.net/code__code/article/details/53885510

  2. [权限管理系统(四)]-spring boot +spring security短信认证+redis整合

    [权限管理系统]spring boot +spring security短信认证+redis整合   现在主流的登录方式主要有 3 种:账号密码登录.短信验证码登录和第三方授权登录,前面一节Sprin ...

  3. Spring Boot 2.x 综合示例-整合thymeleaf、mybatis、shiro、logging、cache开发一个文章发布管理系统

    一.概述 经过HelloWorld示例(Spring Boot 2.x 快速入门(上)HelloWorld示例)( Spring Boot 2.x 快速入门(下)HelloWorld示例详解)两篇的学 ...

  4. 快速搭建基于Spring Boot + Spring Security 环境

    个人博客网:https://wushaopei.github.io/    (你想要这里多有) 1.Spring Security 权限管理框架介绍 简介: Spring Security 提供了基于 ...

  5. 基于Spring Boot+Spring Security+JWT+Vue前后端分离的开源项目

    一.前言 最近整合Spring Boot+Spring Security+JWT+Vue 完成了一套前后端分离的基础项目,这里把它开源出来分享给有需要的小伙伴们 功能很简单,单点登录,前后端动态权限配 ...

  6. Spring Boot 2.0 快速集成整合消息中间件 Kafka

    欢迎关注个人微信公众号: 小哈学Java, 每日推送 Java 领域干货文章,关注即免费无套路附送 100G 海量学习.面试资源哟!! 个人网站: https://www.exception.site ...

  7. 4、Spring Boot 2.x 自动配置原理

    1.4 Spring Boot 自动配置原理 简介 spring boot自动配置功能可以根据不同情况来决定spring配置应该用哪个,不应该用哪个,举个例子: Spring的JdbcTemplate ...

  8. 学记:为spring boot写一个自动配置

    spring boot遵循"约定优于配置"的原则,使用annotation对一些常规的配置项做默认配置,减少或不使用xml配置,让你的项目快速运行起来.spring boot的神奇 ...

  9. Spring boot +Spring Security + Thymeleaf 认证失败返回错误信息

    [Please make sure to select the branch corresponding to the version of Thymeleaf you are using] Stat ...

随机推荐

  1. UVA 11400 Lighting System Design 照明系统设计

    首先是一个贪心,一种灯泡要么全都换,要么全都不换. 先排序,定义状态d[i]为前面i种灯泡的最小花费,状态转移就是从d[j],j<i,加上 i前面的j+1到i-1种灯泡换成i的花费. 下标排序玩 ...

  2. KissXML的XPath选取问题

    XMPPFramework用的XML解析库还是大神自己写的KissXML,有些人生下来就是让人仰望的,哎. 进入主题,如下一段XML: <paramsxmlns="namespace& ...

  3. Catalan 数

    概要 在一些面试的智力题中会遇到此数的变形,如果完全不了解,直接想结果是很困难的,故在此简单介绍一下.   基本定义 Catalan 数的定义根据不同的应用环境有很多不同的定义方式,下面给出一个.   ...

  4. 苹果电脑macbook怎样强制关闭软件

    尝试快捷键Command+Q 选择当前处于界面最前端的应用,同时按住Command+Q退出程序,并不代表强制退出应用,主要用于一些假死的应用. 2 通过快捷键Command+option+Shift+ ...

  5. Java产生GUID

    /** * 产生GUID */public static final String generateGUID(){ UUID uuid = UUID.randomUUID(); return uuid ...

  6. 2017年网络空间安全技术大赛部分writeup

    作为一个bin小子,这次一个bin都没做出来,我很羞愧. 0x00 拯救鲁班七号 具体操作不多说,直接进入反编译源码阶段 可以看到,只要2处的str等于a就可以了,而str是由1处的checkPass ...

  7. 如何查看 JAR 包的源代码

    ava 项目的编译文件经常被打包成 JAR(Java Archive,Java 归档文件)文件,当然,作为学习,有时候也非常想看到这个 JAR 被打包前的源代码是怎么样的. 下面提供几种查看 JAR ...

  8. javaEE(7)_自定义标签&JSTL标签(JSP Standard Tag Library)

    一.自定义标签简介 1.自定义标签主要用于移除Jsp页面中的java代码,jsp禁止出现一行java脚本. 2.使用自定义标签移除jsp页面中的java代码,只需要完成以下两个步骤: •编写一个实现T ...

  9. Java第十二次作业:什么是一维数组?什么是对象数组?吃金币游戏2.0版 新增炸弹功能 新增游戏倒计时功能 新增胜利失败检测功能 使用如鹏游戏引擎制作窗体 一维数组设置金币

    什么是数组? 数组的定义:是用统一的名字代表这批数据,用序号来区分各个数据.数组是无序的数据元素按有序的下标组成的集合,分配固定空间大小的一种容器. 如何理解:其实就是一个同时放很多数据的变量. a= ...

  10. vue-router介绍及简单使用

    一.vue-router介绍 vue-router是vue官方提供的一个路由框架,控制页面路由,使用较为方便. 1.路由模式 hash(浏览器环境默认值),使用 URL hash 值来作路由,支持所有 ...