Spring security权限配置与使用大全

作者:灡亾 时间:2022-03-05 15:37:21 

简介

Spring Security 是为了基于Spring的应用程序提供的声明式安全保护的安全性框架。Spring Security 提供了完整的安全性解决方案,它能够在Web请求级别和方法调用级别处理身份认证和授权。因为基于Spring框架,所以SPring Security充分使用了一览注入和面向切面技术。
Spring Security 本质上是借助一系列的 Servlet Filter来提供各种安全性功能,但这并不需要我们手动去添加或者创建多个Filter。实际上,我们仅需要配置一个Filter即可。
DelegatingFilterProxy 是一个特殊的Filter,他本身并没有做太多工作,而是将工作委托给了一个注入到Spring应用上下文的Filter实现类。

Spring security权限配置与使用大全

在本例中,主要讲解spring-security的配置与使用,实现方式为:

1.将用户、权限、资源(url)采用数据库存储

2.自定义过滤器,代替原有的 FilterSecurityInterceptor

3.自定义实现 UserDetailsService、Filter、AccessDecisionManager和FilterInvocationSecurityMetadataSource并在配置文件进行相应的配置

4.Spring-seculity在自定义用户验证的类加载必须早于Controller层创建

1.配置Spring-seculity.xml


<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
      xmlns:security="http://www.springframework.org/schema/security"
      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
      xsi:schemaLocation="http://www.springframework.org/schema/beans
   http://www.springframework.org/schema/beans/spring-beans.xsd
   http://www.springframework.org/schema/security
   http://www.springframework.org/schema/security/spring-security.xsd">

<security:http security="none" pattern="/login.jsp"/>
   <security:http security="none" pattern="/plugins/**"/>
   <security:http security="none" pattern="/css/**"/>
   <security:http security="none" pattern="/css/style.css"/>
   <security:http security="none" pattern="/img/**"/>
   <security:http security="none" pattern="/filer.jsp"/>
   <security:http security="none" pattern="/favicon.ico"/>
   <security:http  auto-config="true" use-expressions="false">
       <!--优先加载MyFilter自定义过滤器-->
       <security:custom-filter  before="FILTER_SECURITY_INTERCEPTOR" ref="myFilter"/>
       <!--固定用户拦截-->
   <!--<security:intercept-url pattern="/**" access="ROLE_USER" />-->

<!--用户账户和密码表单验证-->
       <!--login-page="拦截跳转页面" login-processing-url="用户登陆验证路径"
           user-paramter=“页面账户名字” password-parameter=“页面密码”
           authentication-failure-url=“登陆失败跳转页面” default-target-rul=“登陆成功跳转页面”
        -->
       <security:form-login login-page="/login.jsp" login-processing-url="/login"
                            username-parameter="username" password-parameter="password"
                            authentication-failure-url="/filer.jsp" default-target-url="/jsp/all-admin-index.jsp"/>
       <!--用户退出登陆 -->
       <security:logout invalidate-session="true" logout-url="/logout" logout-success-url="/login.jsp"/>

<!--禁止跨域请求-->
       <security:csrf disabled="true"/>

</security:http>

<bean id="myFilter" class="filter.MyFilter"/>
   <bean id="userinfo" class="ssm.service.UserinfoService"/>

<!--固定用户账户和密码的验证-->
   <security:authentication-manager >
       <security:authentication-provider user-service-ref="userinfo">
           <!--固定用户名跟密码-->
<!--            <security:user-service>-->
<!--                <security:user name="user" password="{noop}user"-->
<!--                               authorities="ROLE_USER" />-->
<!--            </security:user-service>-->
       </security:authentication-provider>
   </security:authentication-manager>

</beans>

2.配置Web.xml


<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee http://xmlns.jcp.org/xml/ns/javaee/web-app_4_0.xsd"
        version="4.0">
   <display-name>ssm-web</display-name>
   <welcome-file-list>
       <welcome-file>all-admin-login.jsp</welcome-file>
       <welcome-file>index.htm</welcome-file>
       <welcome-file>index.jsp</welcome-file>
       <welcome-file>default.html</welcome-file>
       <welcome-file>default.htm</welcome-file>
       <welcome-file>default.jsp</welcome-file>
   </welcome-file-list>
   <!--全局监听变量-->
   <context-param>
       <param-name>contextConfigLocation</param-name>
       <param-value>classpath:ApplicantContext.xml,classpath:spring-security.xml</param-value>
   </context-param>
   <!-- * -->
   <listener>
           <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
   </listener>
   <!--默认过滤器-->
   <filter>
       <filter-name>springSecurityFilterChain</filter-name>
       <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>
   </filter>
   <filter-mapping>
       <filter-name>springSecurityFilterChain</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>
   <!--spring-mvc中央处理器-->
   <servlet>
       <servlet-name>DispatcherServlet</servlet-name>
       <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
       <init-param>
           <param-name>contextConfigLocation</param-name>
           <param-value>classpath:spring-mvc.xml</param-value>
       </init-param>
       <load-on-startup>1</load-on-startup>
   </servlet>
   <servlet-mapping>
       <servlet-name>DispatcherServlet</servlet-name>
       <url-pattern>/</url-pattern>
   </servlet-mapping>

<!--字符编码转换器-->
   <filter>
       <filter-name>CharacterEncodingFilter</filter-name>
       <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class>
       <init-param>
           <param-name>encoding</param-name>
           <param-value>UTF-8</param-value>
       </init-param>
   </filter>
   <filter-mapping>
       <filter-name>CharacterEncodingFilter</filter-name>
       <url-pattern>/*</url-pattern>
   </filter-mapping>
</web-app>

3.自定义用户角色验证


package ssm.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.User;
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.Service;
import ssm.bean.Role;
import ssm.bean.UserInfo;
import ssm.dao.LoginDao;

import java.util.ArrayList;
import java.util.List;

@Service("userinfo")
public class UserinfoService implements IUserInfoService{

@Autowired
   LoginDao loginDao;

@Override
   public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {//将s传参从数据库查询是否用这个用户
       UserInfo info=loginDao.findByList(s);
       List<Role> list=info.getRoles();
        List<GrantedAuthority> role= new ArrayList<GrantedAuthority>();
       for(Role i:list){
           role.add(new SimpleGrantedAuthority("ROLE_"+i.getRolename()));
       }

System.out.println(s);
       return new User(info.getUsername(), "{noop}"+info.getPassword(),info.getStatus()!=0?true:false,true,true,true, role);

}

}

4.seculity自定义过滤器


package filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.security.access.SecurityMetadataSource;
import org.springframework.security.access.intercept.AbstractSecurityInterceptor;
import org.springframework.security.access.intercept.InterceptorStatusToken;
import org.springframework.security.web.FilterInvocation;

import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;

import javax.servlet.*;
import java.io.IOException;

@Service("myFilter")
public class MyFilter extends AbstractSecurityInterceptor implements Filter {

@Autowired
   private FilterInvocationSecurityMetadataSource securityMetadataSource;

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

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

@Autowired
   public void setMyAccessDecisionManager(MyAccessDescisionManager myAccessDescisionManager) {
       super.setAccessDecisionManager(myAccessDescisionManager);
   }
   @Override
   public void init(FilterConfig filterConfig) throws ServletException {

}
   @Override
   public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)
           throws IOException, ServletException {
       System.out.println("------------MyFilterSecurityInterceptor.doFilter()-----------开始 * 了....");
       FilterInvocation fi = new FilterInvocation(request, response, chain);

InterceptorStatusToken token = super.beforeInvocation(fi);

try {
           fi.getChain().doFilter(fi.getRequest(), fi.getResponse());
       } catch (Exception e) {
           e.printStackTrace();
       } finally {
           super.afterInvocation(token, null);
       }

System.out.println("------------MyFilterSecurityInterceptor.doFilter()----------- * 该方法结束了....");
   }

@Override
   public void destroy() {

}
}

5.自定义用户权限验证


package filter;

import org.springframework.security.access.AccessDecisionManager;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.ConfigAttribute;
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;

import java.util.Collection;
import java.util.Iterator;

@Service
public class MyAccessDescisionManager implements AccessDecisionManager {

@Override
   public void decide(Authentication authentication, Object object, Collection<ConfigAttribute> configAttributes)throws AccessDeniedException, InsufficientAuthenticationException {
       // TODO Auto-generated method stub
        System.out.println("MyAccessDescisionManager.decide()------------------验证用户是否具有一定的权限--------");  
           if(configAttributes==null) return;  
           Iterator<ConfigAttribute> it = configAttributes.iterator();
           while(it.hasNext()){  
               String needResource = it.next().getAttribute();  
               //authentication.getAuthorities()  用户所有的权限  
               for(GrantedAuthority ga:authentication.getAuthorities()){
                   System.out.println("ROLE_"+needResource);
                   System.out.println(ga.getAuthority());
                   if(("ROLE_"+needResource).equals(ga.getAuthority())){  
                       return;  
                   }  
               }  
           }  
           throw new AccessDeniedException("--------MyAccessDescisionManager:decide-------权限认证失败!");  

}

@Override
   public boolean supports(ConfigAttribute attribute) {
       // TODO Auto-generated method stub
       return true;
   }

@Override
   public boolean supports(Class<?> clazz) {
       // TODO Auto-generated method stub
       return true;
   }

}

6.自定义初始化用户角色和权限属性


package filter;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.ConfigAttribute;
import org.springframework.security.access.SecurityConfig;
import org.springframework.security.web.FilterInvocation;
import org.springframework.security.web.access.intercept.FilterInvocationSecurityMetadataSource;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.util.AntPathMatcher;
import ssm.bean.Premission;
import ssm.bean.Role;
import ssm.dao.LoginDao;
import ssm.dao.MapperRoleDao;
import ssm.dao.MapperUserDao;

import java.util.*;

@Service
public class MySecurityMetadataSource implements FilterInvocationSecurityMetadataSource {

/*@Autowired
   private IUserDao userDao; */

@Autowired
   private LoginDao loginDao;

/* 保存资源和权限的对应关系  key-资源url  value-权限 */  
   private static Map<String, Collection<ConfigAttribute>> resourceMap = null;
   private AntPathMatcher urlMatcher = new AntPathMatcher();

public MySecurityMetadataSource() {    
       //loadResourcesDefine();
   }  

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

private void loadResourcesDefine(){  
       resourceMap = new HashMap<String,Collection<ConfigAttribute>>();

System.out.println("MySecurityMetadataSource.loadResourcesDefine()--------------开始加载资源列表数据--------");  
       List<Role> roles;
       try {
           roles = loginDao.findByROleList();
            for(Role role : roles){
                   List<Premission> permissions = role.getPremission();
                   for(Premission permission : permissions){
                       Collection<ConfigAttribute> configAttributes = null;
                       ConfigAttribute configAttribute = new SecurityConfig(role.getRolename());
                       if(resourceMap.containsKey(permission.getUrl())){
                           configAttributes = resourceMap.get(permission.getUrl());
                           configAttributes.add(configAttribute);
                       }else{
                           configAttributes = new ArrayList<ConfigAttribute>() ;
                           configAttributes.add(configAttribute);
                           resourceMap.put(permission.getUrl(), configAttributes);
                       }
                   }
               }
               System.out.println("11");
               Set<String> set = resourceMap.keySet();
               Iterator<String> it = set.iterator();
               int  i=0;
               while(it.hasNext()){
                   String s = it.next();
                   System.out.println(++i+"key:"+s+"|value:"+resourceMap.get(s));
               }
       } catch (Exception e) {
           // TODO Auto-generated catch block
           e.printStackTrace();
       }

}  
   /*  
    * 根据请求的资源地址,获取它所拥有的权限
    */  
   @Override  
   public Collection<ConfigAttribute> getAttributes(Object obj)  
           throws IllegalArgumentException {  
       if(null==resourceMap||resourceMap.size() == 0) {
           loadResourcesDefine();
       }
       //获取请求的url地址  
       String url = ((FilterInvocation)obj).getRequestUrl();
       System.out.println("MySecurityMetadataSource:getAttributes()---------------请求地址为:"+url);  
       Iterator<String> it = resourceMap.keySet().iterator();
       while(it.hasNext()){  
           String _url = it.next();  
           if(url.indexOf("?")!=-1){
               url = url.substring(0, url.indexOf("?"));
           }
           if(urlMatcher.match(_url,url)){
               System.out.println("MySecurityMetadataSource:getAttributes()---------------需要的权限是:"+resourceMap.get(_url));  
               return resourceMap.get(_url);
           }

}
       Collection<ConfigAttribute> nouse = new ArrayList<ConfigAttribute>();
       nouse.add(new SecurityConfig("无相应权限"));
       return nouse;
   }  

@Override  
   public boolean supports(Class<?> arg0) {  
       System.out.println("MySecurityMetadataSource.supports()---------------------");  
       return true;  
   }  

}

来源:https://www.cnblogs.com/haozhiweizhi/p/14794186.html

标签:Spring,security,权限,使用
0
投稿

猜你喜欢

  • java.lang.Runtime.exec的左膀右臂:流输入和流读取详解

    2023-08-06 04:59:03
  • java FastJson的简单用法

    2022-07-07 23:51:47
  • 深入浅析Mybatis的缺陷问题

    2023-07-19 19:39:46
  • C#实现六大设计原则之依赖倒置原则

    2023-06-27 04:02:57
  • Spring Utils工具类常用方法实例

    2023-05-01 05:37:37
  • MyBatis-Plus中最简单的查询操作教程(Lambda)

    2022-03-16 13:43:28
  • InputStream数据结构示例解析

    2022-06-12 20:11:53
  • Android7.0 工具类:DiffUtil详解

    2023-02-24 01:43:46
  • Java8深入学习之熟透Optional

    2023-08-24 21:27:54
  • mybatis新手快速入门以及一些错误汇总

    2023-01-25 13:01:14
  • Java使用BigDecimal进行高精度计算的示例代码

    2023-03-25 10:35:43
  • SpringCloud Feign 服务调用的实现

    2023-09-18 11:07:35
  • Spring Boot2.x集成JPA快速开发的示例代码

    2022-11-21 04:55:41
  • Spring Boot JPA中使用@Entity和@Table的实现

    2023-11-22 11:49:58
  • Android实现房贷计算器

    2022-11-23 17:58:56
  • Java中HashMap里面key为null存放到哪

    2023-11-10 02:46:47
  • 区分Java中的ArrayList和LinkedList

    2021-05-26 11:09:55
  • Java中遍历Map集合的5种方式总结

    2023-04-29 13:14:25
  • java设计模式之工厂方法模式

    2022-08-29 05:14:10
  • struts2自定义拦截器的示例代码

    2021-12-01 16:24:52
  • asp之家 软件编程 m.aspxhome.com