zoukankan      html  css  js  c++  java
  • Spring Security 入门详解

    序:本文主要参考 spring实战 对里面的知识做一个梳理

    1.Spring Security介绍

    Spring Security是基于spring的应用程序提供声明式安全保护的安全性框架,它提供了完整的安全性解决方案,能够在web请求级别和方法调用级别
    处理身份证验证和授权.它充分使用了依赖注入和面向切面的技术.

      Spring security主要是从两个方面解决安全性问题:

    1. web请求级别:使用servlet过滤器保护web请求并限制URL级别的访问
    2. 方法调用级别:使用Spring AOP保护方法调用,确保具有适当权限的用户采用访问安全保护的方法.

    2.Web请求级别的保护

      对于请求级别的安全性来说,主要时通过保护一个或多个URL,使得只有特定的用户才能访问,并其他用户访问该URL的内容.本文主要是基于spring mvc下整合Spring security模块.

    2.1 声明代理Servlet过滤器

      在web中的URL的一般需要过滤器进行保护,所以需要借助一系列的Servlet过滤器提供各种各样的安全性功能.这也需要在web.xml中配置一系列相关的<filter>,使得配置文件臃肿难以阅读.所以Spring security提供了代理Servelt过滤器可以解决该问题.如下面清单所示:

    <filter>
         <filter-name>springSecurityFilterChain</filter-name>
        <filter-class>
            org.springframework.web.filter.DelegatingFilterProxy
        </filter-class>
    </filter>

    DelegatingFilterProxy是一个代理的Servelt过滤器,它主要负责将工作委托给一个javax.servlet.Filter实现类,这个实现类作为一个<bean>已经注册在Spring应用的上下文,且该bean的Id便是上面<filter-name>的名字,即springSecurityFilterChain.  

       springSecurityFilterChain,也可称为FilterChainProxy.它可以链接任意多个其他的过滤器,根据这些过滤器提供不同的安全特性.但是你并不需要在spring配置文件中配置该过滤器的bean和它所链接的其他过滤器

    2.2 配置最小化web安全性和拦截请求

    <http auto-config="true">
         <intercept-url pattern="/admin/**" access="ROLE_ADMIN" />
    </http>

    在spring的配置文件中加入这段代码可以拦截站点/admin分支行下的所有URL请求.并限制只有具备"ROLE_ADMIN"权限的用户才可以访问,"ROLE_ADMIN"是自定义的一个权限.pattern默认使用的是Ant格式。如果需要使用正则表达式则在http 元素的path-type设置为regex。<intercept-url>能够拦截请求,主要是对指定的URL进行保护,如果用户具有访问指定的URL的权限则通过否则拒绝。

      <http>元素将自动创建一个FilterChainProxy以及链中所有的过滤器bean.同时会将FilterChainProxy的bean托管给配置在web.xml的DelegatingFilterProxy.设置auto-config="true"会自动生成一个登陆界面,可以通过http://localhost:8080/你的项目名称/spring_security_login.设置为ture也等价于下面的配置:

    <http>
        <form-login />
      <!--HTTP 基本认证 -->
        <http-basic/>
      <!-- 可以通过logout-url属性设置用户退出的url-->
        <logout />
        <intercept pattern="/**" access="ROLE_DEMO" />
    </http>

    Spring security 3.0以后加入了对SpEL的支持,可以将<http>元素的use-expressions设置为"true"便可使用SpEL。

    <http auto-config="true" use-expressions="true">
       ..
        <intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN')">
    </http>

     Spring Security 支持的所有SpEL表达式如下:

    安全表达式  计算结果
    authentication   用户认证对象
    denyAll   结果始终为false
    hasAnyRole(list of roles)   如果用户被授权指定的任意权限,结果为true
    hasRole(role) 如果用户被授予了指定的权限,结果 为true
    hasIpAddress(IP Adress) 用户地址
    isAnonymous()   是否为匿名用户
    isAuthenticated()   不是匿名用户
    isFullyAuthenticated   不是匿名也不是remember-me认证
    isRemberMe()   remember-me认证
    permitAll 始终true
    principal 用户主要信息对象

    2.3 通过表单安全登陆

       虽然<http>元素设置auto-config="true",可以自动生成一个自动登陆页面。当一般开始都是采用自定义的登陆界面。所以需要进行下面配置:

    <http auto-config="true">
        <!-- 设置登录页配置 login-page指定了登录界面的视图,authentication-failure-url则设置失败后的重定向到相同的登陆界面-->
        <from-login login-processing-url="/static/j_spring_security_check"
        login-page="/login" 
        authentication-failure-url="/login?login_error=t">
    </http>

    在自定义的登录界面中将表单提交地址设置为"/static/j_spring_security_check",同时需要将用户名输入框和密码输入框name分别设置为j_username和j_password 。有些应用中往往会设置记住密码,方便用户访问应用,不需要每次都登录。实现该功能只需要在<http>元素中加入:

    <!--key设置cookie的秘钥的值,默认是SpringSecured。后一个属性指定有效期  -->
    <remember-me key="spitterKey" token-validity-seconds="2419200"/>

    静态页面中加入:

    <input  name="_spring_security_rember_me" type="checkbox"/>

    2.4 强制请求使用https

      https传输数据比较安全,如将用户,密码提交可以使用https保证数据传输的安全。可以进行以下设置,保证每次对指定URL请求,Spring Security都会自动重定向为https请求。不管用户访问时是否加入https.

    <intercept pattern="/admin/**" access="ROLE_DEMO" requires-channel="https" />

    3. 保护视图

      Spring Security提供jsp标签库,支持视图级别的保护,这个标签库包含3个标签:

    1. <security:accesscontrollist> :如果认证用户具有权限列表中的某一个权限,那么这个标签范围的内容将显示。
    2. <security:authentication>: 访问当前用户认证对象的属性。一般用户显示当前用户的用户名之类的。具有的用户认证信息有:
    • authorities:一组用于用户所授予的GrantedAuthority对象
    • credentials:核实用户的凭据
    • detail:认证的附加信息(IP地址,会话ID等)
    • principal:用户的主要信息对象 

      3.<security:authorize>: 如果当前用户满足特定全新,则显示标签范围的内容。例:

    <!-- 显示用户信息, 并将信息复制给var变量,该变量的使用范围为scope的范围。var和scope可以不设置-->
     Hello <security:authentication property="principal.usrname" var="loginId" scope="request">
     <security:authorize access="hasRole('ROLE_ADMIN')">
        如果当前用户有ROLE_ADMIN权限,则显示这部分内容
    </security:authorize>

    <security:authorize>除了使用access来指定权限外还可以根据url设置具体权限,即在拦截请求中指定的url的权限。

    <security:authorize url="/admin/**">
        如果当前用户有/admin/**对应的权限,则显示这部分内容
    </security:authorize>
    4.认证用户
     前面提到很多用户对象和用户权限的问题,他们的关系和定义就是通过认证用户来定义的。 Spring Security提供了以下认证策略:
    • 内存用户存储库,即显示的配置在spring配置文件中。
    • 基于jdbc的用户存储库
    • 基于LDAP的用户存储库
    • OpenID 分散式用户身份识别系统
    • 中心认证服务(CAS)
    • X.509证书
    • 基于JAAS的提供者

      这里主要是介绍基于spirng配置和jdbc的。

    4.1 配置内存用户存储库

    首先建立一个用户服务,配置所有用户和权限信息。然后交给认证管理器管理,认证管理器会将认证的任务交给一个或多个认证提供者。

    <!-- 用户服务-->
    <user-service id="userService">
        <user name="alibaba" password="123456" authorities="ROLE_ADMIN">
        <user name="baidu" password="66666" authorities="ROLE_BAIDU">
        ......
    </user-service>
    <!-- 认证管理器-->
    <authentication-manager>
        <authentication-provider user-service-ref="userService"/>
    </authentication-manager>

    另一种方式将认证提供者和用户服务装配在一起,适用于只有一种用户服务:

    <!-- 认证提供者-->
    <authentication-provider>
        <!-- 用户服务-->
    <user-service id="userService">
        <user name="alibaba" password="123456" authorities="ROLE_ADMIN">
        <user name="baidu" password="66666" authorities="ROLE_BAIDU">
        ......
    </user-service>
    </authentication-provider>

    4.2 基于数据库进行认证

        这个是最常用的是用户认证,因为很多应用都是采用数据库存储用户数据。Spring Security提供了<jdbc-usr-service>.如果只指定了  data-source-ref得数据源,那么spring security会自己为我们写sql语句从数据库中查找用户和权限信息。但一般情况下,提供的查询语句并不能和我们的数据库对应上,所以我们需要自己写sql语句。主要包括以下属性:

    • users-by-username-query:根据用户名查询用户名,密码以及是否可用状态
    • authorities-by-username-query:根据用户名查询用户被用户名和授权的权限。
    • group-authorities-by-username-query:根据用户名查询用户组的权限。 
    <jdbc-user-service id="userService"  data-source-ref="dataSource"
          users-by-username="select username,password, true from user where username=?"
          authories-by-username-query="select username,role from user_role where username=?" />  
    <authentication-manager>
        <authentication-provider user-service-ref="userService"/>
    </authentication-manager>

    5.保护方法调用

      spring security的方法级别的保护是基于Spring AOP技术。首先需要在spring配置文件中加以下配置,才能使spring Security保护那些使用相关注解的方法。

    <global-method-security secured-annotations="enabled" />

       spring Security支持4种方法级别安全性的方法:

    1. 使用@Secured注解方法,这是spring自带的注解方法。@Secured("")内部的字符串不具有SpEL特性,只能是具体的权限。
    2. 使用@JSR-250 @RelosAllowed注解的方法。作用和使用方法与@Secured一样,不同在于它不是spring框架的,所以可以做到和spring框架的解耦。
    3. 使用Spring 方法调用前和调用后注解方法。这些方法支持SpEL.
    4. 匹配一个或多个明确声明的切点方法。

    5.1 @Secured和 @RelosAllowed

    @Secured("ROLE_ADMIN")
    public void addUser(User user){
        ...  
    }
    @RolesAllowed("ROLE_ADMIN")
    public void updateUser(User user){
        ...  
    }

    5.2 使用Spring 方法调用前和调用后注解方法

     可以使用SpEL方法有四种:

    1. @PreAuthorize: 在方法调用前,基于表达式计算结果来限制方法访问
    2. @PostAuthorize: 允许方法调用,但是如果表达式结果为fasle则抛出异常
    3. @PostFilter :允许方法调用,但必须按表达式过滤方法结果。
    4. @PreFilter:允许方法调用,但必须在进入方法前过滤输入值
    @PreAuthorize("hasRole('ROLE_ADMIN')")
    public void addUser(User user){
       //如果具有权限 ROLE_ADMIN 访问该方法
        ....
    }
    
    //returnObject可以获取返回对象user,判断user属性username是否和访问该方法的用户对象的用户名一样。不一样则抛出异常。
    @PostAuthorize("returnObject.user.username==principal.username")
    public User getUser(int userId){
       //允许进入
    ...
        return user;    
    }
    
    //将结果过滤,即选出性别为男的用户
    @PostFilter("returnObject.user.sex=='男' ")
    public List<User> getUserList(){
       //允许进入
    ...
        return user;    
    }

    5.3 匹配一个或多个明确声明的切点方法

        为多个方法设置相同的授权检查,spring security提供了 <protect-pointcut>元素。配置如下:

    <global-method-security secured-annotations="enabled" >
        <protect-pointcut access="ROLE_ADMIN" expression="execution(@com.securitytest.service.UserService**.*(String)"
    </global-method-security>

    转 : https://www.cnblogs.com/jaylon/p/4905769.html

    https://blog.csdn.net/u013117191/article/details/103183628

    https://blog.csdn.net/qq_37771475/article/details/86153799

  • 相关阅读:
    POJ 1953 World Cup Noise
    POJ 1995 Raising Modulo Numbers (快速幂取余)
    poj 1256 Anagram
    POJ 1218 THE DRUNK JAILER
    POJ 1316 Self Numbers
    POJ 1663 Number Steps
    POJ 1664 放苹果
    如何查看DIV被设置什么CSS样式
    独行DIV自适应宽度布局CSS实例与扩大应用范围
    python 从入门到精通教程一:[1]Hello,world!
  • 原文地址:https://www.cnblogs.com/fps2tao/p/14480286.html
Copyright © 2011-2022 走看看