码迷,mamicode.com
首页 > 编程语言 > 详细

Spring security基本使用

时间:2019-10-18 16:05:21      阅读:108      评论:0      收藏:0      [点我收藏+]

标签:cors   返回   filter   html   remember   amp   跨域   匹配   上下   

Spring security 学习记录

1、Spring security 简介

? Spring Security 为 Java EE-based 企业软件应用程序提供全面的安全服务(也就是用户登录页面和相关权限的控制),应用的安全性包括用户认证( Authentication )和用户权限( Authorization )两部分。 用户认证是确定某个用户是否有进入系统的权限,使用用户名密码去认证,也就是所谓的登录;用户权限是确定哪些用户有哪些功能权限,一般都是按角色。

2、主要过滤器

? 众所周知 想要对对Web资源进行保护,最好的办法莫过于Filter,要想对方法调用进行保护,最好的办法莫过于AOP。所以springSecurity在我们进行用户认证以及授予权限的时候,通过各种各样的拦截器来控制权限的访问,从而实现安全。

有篇关于过滤器的文章,有需要可以查看下

https://blog.csdn.net/andy_zhang2007/article/details/84726992

  • WebAsyncManagerIntegrationFilter

    为请求处理过程中可能发生的异步调用准备安全上下文获取途径

  • SecurityContextPersistenceFilter

    整个请求处理过程所需的安全上下文对象SecurityContext的准备和清理不管请求是否针对需要登录才能访问的页面,这里都会确保SecurityContextHolder中出现一个SecurityContext对象:
    1.未登录状态访问登录保护页面:空SecurityContext对象,所含Authentication为null
    2.登录状态访问某个页面:从SecurityContextRepository获取的SecurityContext对象

  • HeaderWriterFilter

    将指定的头部信息写入响应对象

  • CorsFilter

    对请求进行csrf保护

  • LogoutFilter

    检测用户退出登录请求并做相应退出登录处理

  • RequestCacheAwareFilter

    提取请求缓存中缓存的请求
    1.请求缓存在安全机制启动时指定
    2.请求写入缓存在其他地方完成
    3.典型应用场景:
    用户请求保护的页面,
    系统引导用户完成登录认证,
    然后自动跳转到到用户最初请求页面

  • SecurityContextHolderAwareRequestFilter

    包装请求对象使之可以访问SecurityContextHolder,从而使请求真正意义上拥有接口HttpServletRequest中定义的getUserPrincipal这种访问安全信息的能力

  • AnonymousAuthenticationFilter

    如果当前SecurityContext属性Authentication为null,将其替换为一个AnonymousAuthenticationToken`

  • SessionManagementFilter

    检测从请求处理开始到目前是否有用户登录认证,如果有做相应的session管理,比如针对为新登录用户创建新的session(session fixation防护)和设置新的csrf token等。

  • ExceptionTranslationFilter

    处理AccessDeniedException和 AuthenticationException异常,将它们转换成相应的HTTP响应

  • FilterSecurityInterceptor

    一个请求处理的安全处理过滤器链的最后一个,检查用户是否已经认证,如果未认证执行必要的认证,对目标资源的权限检查,如果认证或者权限不足,抛出相应的异常:AccessDeniedException或者AuthenticationException

  • UsernamePasswordAuthenticationFilter

    检测用户名/密码表单登录认证请求并作相应认证处理:
    1.session管理,比如为新登录用户创建新session(session fixation防护)和设置新的csrf token等
    2.经过完全认证的Authentication对象设置到SecurityContextHolder中的SecurityContext上;
    3.发布登录认证成功事件InteractiveAuthenticationSuccessEvent
    4.登录认证成功时的Remember Me处理
    5.登录认证成功时的页面跳转

  • BasicAuthenticationFilter 检测和处理http basic认证

  • DefaultLoginPageGeneratingFilter 生成缺省的登录页面

  • DefaultLogoutPageGeneratingFilter 生成缺省的退出登录页面

  • RememberMeAuthenticationFilter 针对Remember Me登录认证机制的处理逻辑 (免登陆)

3、security核心组件

  • SecurityContextHolder:提供对SecurityContext的访问
  • SecurityContext,:持有Authentication对象和其他可能需要的信息
  • UsernamePasswordAuthenticationFilter 检测用户民密码并做处理
  • AuthenticationManager 其中可以包含多个AuthenticationProvider
  • ProviderManager对象为AuthenticationManager接口的实现类
  • AuthenticationProvider 主要用来进行认证操作的类 调用其中的authenticate()方法去进行认证操作
  • Authentication:Spring Security方式的认证主体
  • GrantedAuthority:对认证主题的应用层面的授权,含当前用户的权限信息,通常使用角色表示
  • UserDetails:构建Authentication对象必须的信息,可以自定义,可能需要访问DB得到
  • UserDetailsService:通过username构建UserDetails对象,通过loadUserByUsername根据userName获取UserDetail对象 (可以在这里基于自身业务进行自定义的实现 如通过数据库,xml,缓存获取等)
  • passwordEncoder 密码加密器

4、主要流程

  1. 如图:当用户登录时,前端将用户输入的用户名、密码信息传输到后台( UsernamePasswordAuthenticationFilter ),后台用一个类对象将其封装起来,通常使用的是UsernamePasswordAuthenticationToken这个类,然后在 AuthenticationManager 中获取用户,进行加密,认证对比等相关操作,返回是否是系统用户。
    技术图片
  2. 比较两者的密码,如果密码正确就成功登陆,同时把包含着用户的用户名、密码、所具有的权限等信息的类对象放到SecurityContextHolder(安全上下文容器,类似Session)中去。

  3. 用户访问一个资源的时候,首先判断是否是受限资源。如果是的话还要判断当前是否未登录,没有的话就跳到登录页面。

  4. 如果用户已经登录,访问一个受限资源的时候,程序要根据url去数据库中取出该资源所对应的所有可以访问的角色,然后拿着当前用户的所有角色一一对比,判断用户是否可以访问。

  5. 用户认证的实现方式有很多种,主要体现在 AuthenticationProvider 接口的实现中,目前主流的实现:

    DaoAuthenticationProvider 利用数据库数据进行登录认证

    JassAuthenticationProvider Java 认证和授权服务

    CasAuthenticationProvider 利用单点登录进行登录认证

    LdapAuthenticationProvider 跨域身份认证

5、简单代码实现

本例子是基于老版本3.2.7的XML一种实现,需要基于confirm配置,请查看更高版本,地址如下:

https://www.docs4dev.com/docs/zh/spring-security/4.2.10.RELEASE/reference

web.xml配置,添加springSecurityFilterChain配置

  <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>

Security.xml配置

具体配置讲解可以参考

https://www.cnblogs.com/yyxxn/p/8080141.html

<sec:http pattern="/loggedOut.html" security="none" />
    <!-- 配置免登录的资源 -->
    <sec:http pattern="/toLogin" security="none" />
    <sec:http pattern="/loginError" security="none" />
    <!-- IS_AUTHENTICATED_ANONYMOUSLY 允许匿名用户进入 -->
    <!-- IS_AUTHENTICATED_FULLY 允许登录用户进入 -->
    <!-- IS_AUTHENTICATED_REMEMBERED 允许登录用户和rememberMe用户进入 -->

   <!--auto-config = true 则使用from-login. 如果不使用该属性 则默认为http-basic(没有session).--> 
    <!-- lowercase-comparisons:表示URL比较前先转为小写。-->  
    <!-- path-type:表示使用Apache Ant的匹配模式。-->  
    <!--access-denied-page:访问拒绝时转向的页面。-->  
    <!-- access-decision-manager-ref:指定了自定义的访问策略管理器。-->  
    <!--isAuthenticated() 当前用户是否已通过身份验证-->
    <!--access="hasRole('SUPER_ADMIN') 代表该地址只有权限SUPER_ADMIN才能查看-->
    <sec:http use-expressions="true"  auto-config="true" >
        <sec:intercept-url pattern="/user/*" access="hasRole('SUPER_ADMIN')" />
        <sec:intercept-url pattern="/**" access="isAuthenticated()" />

        <!--login-page:指定登录页面。  -->  
<!-- login-processing-url:指定了客户在登录页面中按下 Sign In 按钮时要访问的 URL。-->  
        <!-- authentication-failure-url:指定了身份验证失败时跳转到的页面。-->  
        <!-- default-target-url:指定了成功进行身份验证和授权后默认呈现给用户的页面。-->  
<!-- always-use-default-target:指定了是否在身份验证通过后总是跳转到default-target-url属性指定的URL。 
-->  
        <sec:form-login login-page="/toLogin"
                        login-processing-url="/login"
                        always-use-default-target="true"
                        default-target-url="/index"
                        authentication-failure-url="/toLogin?error=1"
        />
        <!--logout-url:指定了用于响应退出系统请求的URL。其默认值为:/j_spring_security_logout。-->
        <!-- logout-success-url:退出系统后转向的URL。-->
        <!-- invalidate-session:指定在退出系统时是否要销毁Session。-->
        <sec:logout invalidate-session="true" logout-success-url="/toLogin"
                    logout-url="/j_spring_cas_security_logout" />
        <!-- 实现免登陆验证 -->
        <sec:remember-me />
    </sec:http>

    <bean id="myFilter" class="org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter">
        <property name="authenticationManager" ref="casAuthenticationManager" />
    </bean>

    <bean id="daoAuthenticationProvider" class="org.springframework.security.authentication.dao.DaoAuthenticationProvider"
          p:userDetailsService-ref="userDetailsService" p:passwordEncoder-ref="md5PasswordEncoder">
    </bean>
<!--md5加密方式-->
    <bean id = "md5PasswordEncoder" class="org.springframework.security.authentication.encoding.Md5PasswordEncoder"></bean>

<!--数据使用直接查询数据库方式,也可以实现userDetailsService接口-->
    <bean id="casDataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="${JDBC.driverClassName}" />
        <property name="url" value="${JDBC.url}" />
        <property name="username" value="${JDBC.username}" />
        <property name="password" value="${JDBC.password}" />
    </bean>
    <sec:jdbc-user-service id="userDetailsService" data-source-ref="casDataSource"
                           users-by-username-query="
                    SELECT
                        u.account username,
                        u.`password`,
                        u.displayFlag enabled
                    FROM
                        core_user AS u
                    WHERE
                        u.displayFlag = 1
                    AND
                        u.enabledFlag = 1
                    AND
                        u.account = ? "
                           authorities-by-username-query="
                    SELECT
                        u.account username,
                        r.`code` role
                    FROM
                        core_role AS r
                    LEFT JOIN core_user_role AS ur ON r.id = ur.roleId
                    INNER JOIN core_user AS u ON ur.userId = u.id
                    WHERE
                        u.displayFlag = 1
                    AND
                        u.enabledFlag = 1
                    AND
                        u.account = ?" />

login.jsp如下

<form id="fm1" action="/login" method="post" novalidate="novalidate">
            <div class="form-group form-username">
                <input type="text" class="form-control" id="username" name="j_username"  placeholder="Name">
            </div>
            <div class="form-group form-password">
                <input id="password" name="j_password"  type="password">
            </div>
            <div class="form-checkbox">
          <span class="checkbox pointer checked">
          <input type="checkbox" id="_spring_security_remember_me" name="_spring_security_remember_me" checked="checked">
          </span>&nbsp;&nbsp;7天免登录
            </div>
            <div class="form-group">
                <button type="submit" class="btn id="loginBtn">登 录
                </button>
            </div>
        </form>

注意:如果是使用UsernamePasswordAuthenticationFilter ,得注意使用的版本,每个版本对应的字段可能不一样,需要打开源码看看。

在3.2.7中,用户名(j_username),密码(j_password),记住密码(_spring_security_remember_me)。

在4.2中,用户名(username),密码(password)

在学习的过程中,借鉴了前辈们的文章,参考如下

https://blog.csdn.net/liushangzaibeijing/article/details/81220610

https://blog.csdn.net/andy_zhang2007/article/details/84726992

https://www.docs4dev.com/docs/zh/spring-security/4.2.10.RELEASE/reference

Spring security基本使用

标签:cors   返回   filter   html   remember   amp   跨域   匹配   上下   

原文地址:https://www.cnblogs.com/yz-yang/p/11697942.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!