SpringBoot+Spring Security + spring boot jpa 实现权限管理

一 建表

权限管理需实现5张表:用户表、角色表、用户角色对应表、权限表、权限角色对应表

用户表
CREATE TABLE platform_user (
id bigint(20) NOT NULL AUTO_INCREMENT,
username varchar(50) NOT NULL,
password varchar(100) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

角色表
CREATE TABLE platform_role (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(50) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT=‘这只是角色表’;

用户角色对应表
CREATE TABLE platform_role_user (
id int(11) NOT NULL AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
role_id int(11) NOT NULL,
PRIMARY KEY (id),
KEY FKt6466kf26ep5v3rfcya2sxi53 (role_id),
KEY FKfwy3bmkplk822fdp5o1btjyyv (user_id),
CONSTRAINT FKfwy3bmkplk822fdp5o1btjyyv FOREIGN KEY (user_id) REFERENCES platform_user (id),
CONSTRAINT FKt6466kf26ep5v3rfcya2sxi53 FOREIGN KEY (role_id) REFERENCES platform_role (id)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

权限表
CREATE TABLE platform_sys_permission (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(50) NOT NULL,
description varchar(50) NOT NULL,
url varchar(100) NOT NULL,
pid int(11) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT=‘权限表’;
注意:如果存在子权限,一定要把最大的权限放在最后,否则在下面权限判定时,会出问题。

5. 权限角色对应表

    CREATE TABLE `platform_permission_role` (
     `id` int(11) NOT NULL AUTO_INCREMENT,
     `role_id` int(11) NOT NULL,
     `permission_id` int(11) NOT NULL,
     PRIMARY KEY (`id`),
     KEY `role_id` (`role_id`)
     ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COMMENT='角色权限管理表';

二 实体类

User.java

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = “username”,nullable = false,length = 50)
private String userName;

@Column(name = “password”,nullable = false,length = 100)
private String password;

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = “platform_role_user”, joinColumns = @JoinColumn(name = “user_id”, referencedColumnName = “id”), inverseJoinColumns = @JoinColumn(name = “role_id”, referencedColumnName = “id”))
private List roles;
省略 get set
Role.java

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

/**

  • 权限名
    */
    @Column(name = “name”, nullable = false,length = 50)
    private String name;

RoleUser.java

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@Column(name = "user_id")
private Long userId;

@Column(name = "role_id")
private Integer roleId;

Permission.java

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

/**
 * 权限名
 */
@Column(name = "name",nullable = false)
private String name;

/**
 * 权限描述
 */
@Column(name = "description", nullable = false)
private String description;

/**
 * 权限的url
 */
@Column(name = "url", nullable = false)
private String url;

/**
 * 父节点id
 */
@Column(name = "pid")
private Integer pid;

PermissionRole.java

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@Column(name = "role_id")
private Integer roleId;

@Column(name = "permission_id")
private Integer permissionId;

三 security 配置类

/**

  • @author: 易明星

  • @Modified By:

  • @Date: Create in 13:27 2019/6/24

  • @Description: 权限配置
    */
    @Configuration
    @EnableGlobalMethodSecurity(prePostEnabled=true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyFilterSecurityInterceptor myFilterSecurityInterceptor;

    @Autowired
    private CustomUserDetailService userDetailService;

    /**

    • 密码加密的方式
    • @return
      */
      @Bean
      public BCryptPasswordEncoder passwordEncoder() {
      return new BCryptPasswordEncoder();
      }

    /**

    • 加密密码
    • @param auth
    • @throws Exception
      */
      @Override
      protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder());
      }

    /**

    • security 具体的配置
    • @param http
    • @throws Exception
      */
      @Override
      protected void configure(HttpSecurity http) throws Exception {
      http
      .csrf().disable() //csrf不可用
      .authorizeRequests()
      .antMatchers("/static/", "/css/", “/js/", "/images/”, “/lib/**”).permitAll() //访问允许静态文件
      .antMatchers("/", “/login”).permitAll()//允许访问登录页
      .and()
      .formLogin()
      .loginPage("/login")//自定义登录页
      .failureUrl("/login?error")//指定登录失败页
      .defaultSuccessUrl("/driver/system.html") //登录成功跳转页
      .usernameParameter(“name”)//页面上使用的是 th:field 则需要写这个,否则不需要
      .passwordParameter(“passWd”)
      .and()
      .headers().frameOptions().disable()//in a frame because it set ‘X-Frame-Options’ to ‘deny’.有这个问题则写
      .and()
      .logout().logoutSuccessUrl("/").permitAll(); //退出登录跳转页
      http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);
      }
      }

四 service

CustomUserDetailService.java

@Service
public class CustomUserDetailService implements UserDetailsService {
private final static Logger logger = LogManager.getLogger(CustomUserDetailService.class);

@Autowired
private UserRepository userRepository;

@Autowired
private PermissionDao permissionDao;

/**
 * 根据用户名来取得用户信息,判断用户存不存在,同时取得该用户的权限
 * 这里不判断密码是否正确
 * @param name
 * @return
 * @throws UsernameNotFoundException
 */
@Override
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
    User user = userRepository.findByUserName(name);
    /**
     * 权限
     */
    if (null!=user){
        List<Permission> permissions = permissionDao.findByAdminUserId(user.getId());
        List<GrantedAuthority> grantedAuthorities = new ArrayList <>();
        for (Permission permission : permissions) {
            if (permission != null && permission.getName()!=null) {
                GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getName());
                //1:此处将权限信息添加到 GrantedAuthority 对象中,在后面进行全权限验证时会使用GrantedAuthority 对象。
                grantedAuthorities.add(grantedAuthority);
            }
        }
        logger.log(Level.INFO,"name="+user.getUserName()+"\t "+"权限="+grantedAuthorities);
        return new org.springframework.security.core.userdetails.User(
                user.getUserName(),
                user.getPassword(),
                grantedAuthorities);
    }else {
        throw new UsernameNotFoundException("admin: " + name + " do not exist!");
    }

    /**
     * 不管权限
     */
    /*if (user==null){
        logger.error("Not Found name "+ name);
        throw new UsernameNotFoundException("Not Found name "+ name);
    }
    return new org.springframework.security.core.userdetails.User(
                user.getUserName(),
                user.getPassword(),
                grantedAuthorities);*/
}
private static List<GrantedAuthority> getAuthorities (List<Role> roles) {

    List<GrantedAuthority> authorities = new ArrayList<>();
    for (Role role:roles){
        authorities.add(new SimpleGrantedAuthority(role.getName()));
    }
    return authorities;
}

}
MyAccessDecisionManager.java
/**

  • @author: 易明星

  • @Modified By:

  • @Date: Create in 11:17 2019/6/25

  • @Description:
    */
    @Service
    public class MyAccessDecisionManager implements AccessDecisionManager {

    /**

    • decide 方法是判定是否拥有权限的决策方法,
    • object 包含客户端发起的请求的requset信息,可转换为
    •    HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
      
    • authentication 是 CustomUserService 中循环添加到 GrantedAuthority 对象中的权限信息集合.
    • configAttributes 为MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法返回的结果,
    • 此方法是为了判定用户请求的url是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。
    • @param authentication
    • @param object
    • @param configAttributes
    • @throws AccessDeniedException
    • @throws InsufficientAuthenticationException
      */
      @Override
      public void decide(Authentication authentication, Object object, Collection configAttributes)
      throws AccessDeniedException, InsufficientAuthenticationException {
      if(null== configAttributes || configAttributes.size() <=0) {
      return;
      }
      ConfigAttribute c;
      String needRole;
      for(Iterator iter = configAttributes.iterator(); iter.hasNext(); ) {
      c = iter.next();
      needRole = c.getAttribute();
      for(GrantedAuthority ga : authentication.getAuthorities()) {//authentication CustomUserDetailService中循环添加到 GrantedAuthority 对象中的权限信息集合
      if(needRole.trim().equals(ga.getAuthority())) {
      return;
      }
      }
      }
      throw new AccessDeniedException(“no right”);
      }

    @Override
    public boolean supports(ConfigAttribute attribute) {
    return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
    return true;
    }
    }
    MyInvocationSecurityMetadataSourceService.java
    /**

  • @author: 易明星

  • @Modified By:

  • @Date: Create in 11:22 2019/6/25

  • @Description:
    */
    @Service
    public class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource {
    private final static Logger logger = LogManager.getLogger(CustomUserDetailService.class);

    @Autowired
    private PermissionDao permissionDao;

    private Map<String, Collection> map =null;

    /**

    • 加载权限表中所有权限
      */
      public void loadResourceDefine(){
      map = new LinkedHashMap<>();
      Collection array;
      ConfigAttribute cfg;
      List permissions = permissionDao.findAll();
      for(Permission permission : permissions) {
      array = new ArrayList<>();
      cfg = new SecurityConfig(permission.getName());
      //此处只添加了用户的名字,其实还可以添加更多权限的信息,例如请求方法到ConfigAttribute的集合中去。
      // 此处添加的信息将会作为MyAccessDecisionManager类的decide的第三个参数。
      array.add(cfg);
      //用权限的getUrl() 作为map的key,用ConfigAttribute的集合作为 value,
      map.put(permission.getUrl(), array);
      }

    }

    /**

    • 此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。
      */
      @Override
      public Collection getAttributes(Object object) throws IllegalArgumentException {
      if(map ==null) loadResourceDefine();
      //object 中包含用户请求的request 信息
      // 想办法把map反过来
      HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
      AntPathRequestMatcher matcher;
      String resUrl;
      for(Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
      resUrl = iter.next();
      matcher = new AntPathRequestMatcher(resUrl);
      if(matcher.matches(request)) {
      return map.get(resUrl);
      }
      }
      return null;
      }

    @Override
    public Collection getAllConfigAttributes() {
    return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
    return true;
    }

五 自定义security 过滤器 拦截 url请求

MyFilterSecurityInterceptor.java
/**

  • @author: 易明星

  • @Modified By:

  • @Date: Create in 11:20 2019/6/25

  • @Description: 自定义security的过滤器
    */
    @Service
    public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {

    @Autowired
    private FilterInvocationSecurityMetadataSource securityMetadataSource;

    @Autowired
    public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) {
    super.setAccessDecisionManager(myAccessDecisionManager);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    FilterInvocation fi = new FilterInvocation(request, response, chain);
    invoke(fi);
    }

    public void invoke(FilterInvocation fi) throws IOException, ServletException {
    //fi里面有一个被拦截的url
    //里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限
    //再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够
    InterceptorStatusToken token = super.beforeInvocation(fi);
    try {
    //执行下一个拦截器
    fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
    } finally {
    super.afterInvocation(token, null);
    }
    }

    @Override
    public void destroy() {

    }

    @Override
    public Class<?> getSecureObjectClass() {
    return FilterInvocation.class;
    一 建表

权限管理需实现5张表:用户表、角色表、用户角色对应表、权限表、权限角色对应表

用户表
CREATE TABLE platform_user (
id bigint(20) NOT NULL AUTO_INCREMENT,
username varchar(50) NOT NULL,
password varchar(100) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

角色表
CREATE TABLE platform_role (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(50) NOT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8 COMMENT=‘这只是角色表’;

用户角色对应表
CREATE TABLE platform_role_user (
id int(11) NOT NULL AUTO_INCREMENT,
user_id bigint(20) NOT NULL,
role_id int(11) NOT NULL,
PRIMARY KEY (id),
KEY FKt6466kf26ep5v3rfcya2sxi53 (role_id),
KEY FKfwy3bmkplk822fdp5o1btjyyv (user_id),
CONSTRAINT FKfwy3bmkplk822fdp5o1btjyyv FOREIGN KEY (user_id) REFERENCES platform_user (id),
CONSTRAINT FKt6466kf26ep5v3rfcya2sxi53 FOREIGN KEY (role_id) REFERENCES platform_role (id)
) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;

权限表
CREATE TABLE platform_sys_permission (
id int(11) NOT NULL AUTO_INCREMENT,
name varchar(50) NOT NULL,
description varchar(50) NOT NULL,
url varchar(100) NOT NULL,
pid int(11) DEFAULT NULL,
PRIMARY KEY (id)
) ENGINE=InnoDB AUTO_INCREMENT=6 DEFAULT CHARSET=utf8 COMMENT=‘权限表’;
注意:如果存在子权限,一定要把最大的权限放在最后,否则在下面权限判定时,会出问题。

5. 权限角色对应表

CREATE TABLE platform_permission_role (
         id int(11) NOT NULL AUTO_INCREMENT,
         role_id int(11) NOT NULL,
         permission_id int(11) NOT NULL,
         PRIMARY KEY (id),
         KEY role_id (role_id)
         ) ENGINE=InnoDB AUTO_INCREMENT=14 DEFAULT CHARSET=utf8 COMMENT=‘角色权限管理表’;

二 实体类

User.java

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

@Column(name = “username”,nullable = false,length = 50)
private String userName;

@Column(name = “password”,nullable = false,length = 100)
private String password;

@ManyToMany(fetch = FetchType.EAGER)
@JoinTable(name = “platform_role_user”, joinColumns = @JoinColumn(name = “user_id”, referencedColumnName = “id”), inverseJoinColumns = @JoinColumn(name = “role_id”, referencedColumnName = “id”))
private List roles;
省略 get set
Role.java

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

/**

  • 权限名
    */
    @Column(name = “name”, nullable = false,length = 50)
    private String name;

RoleUser.java

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@Column(name = "user_id")
private Long userId;

@Column(name = "role_id")
private Integer roleId;

Permission.java

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

/**
 * 权限名
 */
@Column(name = "name",nullable = false)
private String name;

/**
 * 权限描述
 */
@Column(name = "description", nullable = false)
private String description;

/**
 * 权限的url
 */
@Column(name = "url", nullable = false)
private String url;

/**
 * 父节点id
 */
@Column(name = "pid")
private Integer pid;

PermissionRole.java

@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;

@Column(name = "role_id")
private Integer roleId;

@Column(name = "permission_id")
private Integer permissionId;

三 security 配置类

/**

  • @author: 易明星

  • @Modified By:

  • @Date: Create in 13:27 2019/6/24

  • @Description: 权限配置
    */
    @Configuration
    @EnableGlobalMethodSecurity(prePostEnabled=true)
    public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    private MyFilterSecurityInterceptor myFilterSecurityInterceptor;

    @Autowired
    private CustomUserDetailService userDetailService;

    /**

    • 密码加密的方式
    • @return
      */
      @Bean
      public BCryptPasswordEncoder passwordEncoder() {
      return new BCryptPasswordEncoder();
      }

    /**

    • 加密密码
    • @param auth
    • @throws Exception
      */
      @Override
      protected void configure(AuthenticationManagerBuilder auth) throws Exception {
      auth.userDetailsService(userDetailService).passwordEncoder(passwordEncoder());
      }

    /**

    • security 具体的配置
    • @param http
    • @throws Exception
      */
      @Override
      protected void configure(HttpSecurity http) throws Exception {
      http
      .csrf().disable() //csrf不可用
      .authorizeRequests()
      .antMatchers("/static/", "/css/", “/js/", "/images/”, “/lib/**”).permitAll() //访问允许静态文件
      .antMatchers("/", “/login”).permitAll()//允许访问登录页
      .and()
      .formLogin()
      .loginPage("/login")//自定义登录页
      .failureUrl("/login?error")//指定登录失败页
      .defaultSuccessUrl("/driver/system.html") //登录成功跳转页
      .usernameParameter(“name”)//页面上使用的是 th:field 则需要写这个,否则不需要
      .passwordParameter(“passWd”)
      .and()
      .headers().frameOptions().disable()//in a frame because it set ‘X-Frame-Options’ to ‘deny’.有这个问题则写
      .and()
      .logout().logoutSuccessUrl("/").permitAll(); //退出登录跳转页
      http.addFilterBefore(myFilterSecurityInterceptor, FilterSecurityInterceptor.class);
      }
      }

四 service

CustomUserDetailService.java

@Service
public class CustomUserDetailService implements UserDetailsService {
private final static Logger logger = LogManager.getLogger(CustomUserDetailService.class);

@Autowired
private UserRepository userRepository;

@Autowired
private PermissionDao permissionDao;

/**
 * 根据用户名来取得用户信息,判断用户存不存在,同时取得该用户的权限
 * 这里不判断密码是否正确
 * @param name
 * @return
 * @throws UsernameNotFoundException
 */
@Override
public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
    User user = userRepository.findByUserName(name);
    /**
     * 权限
     */
    if (null!=user){
        List<Permission> permissions = permissionDao.findByAdminUserId(user.getId());
        List<GrantedAuthority> grantedAuthorities = new ArrayList <>();
        for (Permission permission : permissions) {
            if (permission != null && permission.getName()!=null) {
                GrantedAuthority grantedAuthority = new SimpleGrantedAuthority(permission.getName());
                //1:此处将权限信息添加到 GrantedAuthority 对象中,在后面进行全权限验证时会使用GrantedAuthority 对象。
                grantedAuthorities.add(grantedAuthority);
            }
        }
        logger.log(Level.INFO,"name="+user.getUserName()+"\t "+"权限="+grantedAuthorities);
        return new org.springframework.security.core.userdetails.User(
                user.getUserName(),
                user.getPassword(),
                grantedAuthorities);
    }else {
        throw new UsernameNotFoundException("admin: " + name + " do not exist!");
    }

    /**
     * 不管权限
     */
    /*if (user==null){
        logger.error("Not Found name "+ name);
        throw new UsernameNotFoundException("Not Found name "+ name);
    }
    return new org.springframework.security.core.userdetails.User(
                user.getUserName(),
                user.getPassword(),
                grantedAuthorities);*/
}
private static List<GrantedAuthority> getAuthorities (List<Role> roles) {

    List<GrantedAuthority> authorities = new ArrayList<>();
    for (Role role:roles){
        authorities.add(new SimpleGrantedAuthority(role.getName()));
    }
    return authorities;
}

}
MyAccessDecisionManager.java
/**

  • @author: 易明星

  • @Modified By:

  • @Date: Create in 11:17 2019/6/25

  • @Description:
    */
    @Service
    public class MyAccessDecisionManager implements AccessDecisionManager {

    /**

    • decide 方法是判定是否拥有权限的决策方法,
    • object 包含客户端发起的请求的requset信息,可转换为
    •    HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
      
    • authentication 是 CustomUserService 中循环添加到 GrantedAuthority 对象中的权限信息集合.
    • configAttributes 为MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法返回的结果,
    • 此方法是为了判定用户请求的url是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。
    • @param authentication
    • @param object
    • @param configAttributes
    • @throws AccessDeniedException
    • @throws InsufficientAuthenticationException
      */
      @Override
      public void decide(Authentication authentication, Object object, Collection configAttributes)
      throws AccessDeniedException, InsufficientAuthenticationException {
      if(null== configAttributes || configAttributes.size() <=0) {
      return;
      }
      ConfigAttribute c;
      String needRole;
      for(Iterator iter = configAttributes.iterator(); iter.hasNext(); ) {
      c = iter.next();
      needRole = c.getAttribute();
      for(GrantedAuthority ga : authentication.getAuthorities()) {//authentication CustomUserDetailService中循环添加到 GrantedAuthority 对象中的权限信息集合
      if(needRole.trim().equals(ga.getAuthority())) {
      return;
      }
      }
      }
      throw new AccessDeniedException(“no right”);
      }

    @Override
    public boolean supports(ConfigAttribute attribute) {
    return true;
    }

    @Override
    public boolean supports(Class<?> clazz) {
    return true;
    }
    }
    MyInvocationSecurityMetadataSourceService.java
    /**

  • @author: 易明星

  • @Modified By:

  • @Date: Create in 11:22 2019/6/25

  • @Description:
    */
    @Service
    public class MyInvocationSecurityMetadataSourceService implements FilterInvocationSecurityMetadataSource {
    private final static Logger logger = LogManager.getLogger(CustomUserDetailService.class);

    @Autowired
    private PermissionDao permissionDao;

    private Map<String, Collection> map =null;

    /**

    • 加载权限表中所有权限
      */
      public void loadResourceDefine(){
      map = new LinkedHashMap<>();
      Collection array;
      ConfigAttribute cfg;
      List permissions = permissionDao.findAll();
      for(Permission permission : permissions) {
      array = new ArrayList<>();
      cfg = new SecurityConfig(permission.getName());
      //此处只添加了用户的名字,其实还可以添加更多权限的信息,例如请求方法到ConfigAttribute的集合中去。
      // 此处添加的信息将会作为MyAccessDecisionManager类的decide的第三个参数。
      array.add(cfg);
      //用权限的getUrl() 作为map的key,用ConfigAttribute的集合作为 value,
      map.put(permission.getUrl(), array);
      }

    }

    /**

    • 此方法是为了判定用户请求的url 是否在权限表中,如果在权限表中,则返回给 decide 方法,用来判定用户是否有此权限。如果不在权限表中则放行。
      */
      @Override
      public Collection getAttributes(Object object) throws IllegalArgumentException {
      if(map ==null) loadResourceDefine();
      //object 中包含用户请求的request 信息
      // 想办法把map反过来
      HttpServletRequest request = ((FilterInvocation) object).getHttpRequest();
      AntPathRequestMatcher matcher;
      String resUrl;
      for(Iterator iter = map.keySet().iterator(); iter.hasNext(); ) {
      resUrl = iter.next();
      matcher = new AntPathRequestMatcher(resUrl);
      if(matcher.matches(request)) {
      return map.get(resUrl);
      }
      }
      return null;
      }

    @Override
    public Collection getAllConfigAttributes() {
    return null;
    }

    @Override
    public boolean supports(Class<?> clazz) {
    return true;
    }

五 自定义security 过滤器 拦截 url请求

MyFilterSecurityInterceptor.java
/**

  • @author: 易明星

  • @Modified By:

  • @Date: Create in 11:20 2019/6/25

  • @Description: 自定义security的过滤器
    */
    @Service
    public class MyFilterSecurityInterceptor extends AbstractSecurityInterceptor implements Filter {

    @Autowired
    private FilterInvocationSecurityMetadataSource securityMetadataSource;

    @Autowired
    public void setMyAccessDecisionManager(MyAccessDecisionManager myAccessDecisionManager) {
    super.setAccessDecisionManager(myAccessDecisionManager);
    }

    @Override
    public void init(FilterConfig filterConfig) throws ServletException {

    }

    @Override
    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {
    FilterInvocation fi = new FilterInvocation(request, response, chain);
    invoke(fi);
    }

    public void invoke(FilterInvocation fi) throws IOException, ServletException {
    //fi里面有一个被拦截的url
    //里面调用MyInvocationSecurityMetadataSource的getAttributes(Object object)这个方法获取fi对应的所有权限
    //再调用MyAccessDecisionManager的decide方法来校验用户的权限是否足够
    InterceptorStatusToken token = super.beforeInvocation(fi);
    try {
    //执行下一个拦截器
    fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
    } finally {
    super.afterInvocation(token, null);
    }
    }

    @Override
    public void destroy() {

    }

    @Override
    public Class<?> getSecureObjectClass() {
    return FilterInvocation.class;
    }

    @Override
    public SecurityMetadataSource obtainSecurityMetadataSource() {
    return this.securityMetadataSource;
    }
    }

    }

    @Override
    public SecurityMetadataSource obtainSecurityMetadataSource() {
    return this.securityMetadataSource;
    }
    }


版权声明:本文为weixin_44533475原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。