spring-security-5.0版本的xml基本配置

<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/security"
    xmlns:beans="http://www.springframework.org/schema/beans" 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">
    <beans:description>SpringSecurity安全配置</beans:description>
    <!-- http安全配置 -->
    <http use-expressions="true" auto-config="false"
        entry-point-ref="authenticationEntryPoint" name="empire"
        authentication-manager-ref="authenticationManager">
        <!-- session过滤器 -->
        <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />
        <!-- <intercept-url pattern="/static/**" access="permitAll" /> -->
        <intercept-url pattern="/**/*.jpg" access="permitAll" />
        <intercept-url pattern="/**/*.png" access="permitAll" />
        <intercept-url pattern="/**/*.gif" access="permitAll" />
        <intercept-url pattern="/**/*.css" access="permitAll" />
        <intercept-url pattern="/**/*.js" access="permitAll" />
        <!-- 尝试访问没有权限的页面时跳转的页面 -->
        <access-denied-handler error-page="/static/403.html" />
        <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR" />
        <!-- ajax登录过滤器 -->
        <!-- <custom-filter before="FORM_LOGIN_FILTER" ref="ajaxLoginFilter" /> -->
        <custom-filter position="FORM_LOGIN_FILTER" ref="adminAjaxLoginFilter" />
        <!-- <custom-filter after="FORM_LOGIN_FILTER" ref="loginFilter" /> -->
        <headers>
            <frame-options policy="SAMEORIGIN"></frame-options>
        </headers>
        <!-- 只cache get,避免ajax post 被cache -->
        <request-cache ref="httpSessionRequestCache" />
        <session-management
            session-authentication-strategy-ref="sessionAuthenticationStrategy" />
        <!-- 注销过滤器 -->
        <!-- <logout invalidate-session="true" logout-success-url="/admin/login.html?logout=true" 
            logout-url="/j_spring_security_logout" /> -->
        <!-- 启用安全策略 -->
        <csrf disabled="false" token-repository-ref="csrfTokenRepository"
            request-matcher-ref="csrfSecurityRequestMatcher" />
        <custom-filter ref="rememberMeFilter" position="REMEMBER_ME_FILTER" />
        <custom-filter ref="logoutFilter" position="LOGOUT_FILTER" />
        <access-denied-handler ref="accessDeniedHandler" />
    </http>
    <beans:bean id="csrfSecurityRequestMatcher"
        class="pn.empire.security.handler.CsrfSecurityRequestMatcher">
        <beans:property name="execludeUrls">
            <beans:list>
                <beans:value>/workorder/adminuploadattachment.html</beans:value>
                <beans:value>/face/</beans:value>
            </beans:list>
        </beans:property>
    </beans:bean>
    <!-- -->
    <beans:bean id="accessDeniedHandler"
        class="pn.empire.security.handler.AccessDeniedHandlerImpl">
        <beans:property name="errorPage" value="/static/405.html"></beans:property>
    </beans:bean>
    <!--remember-me拦截器 -->
    <beans:bean id="rememberMeFilter"
        class="org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
        <beans:constructor-arg ref="authenticationManager" />
        <beans:constructor-arg ref="rememberMeServices" />
    </beans:bean>
    <beans:bean id="rememberMeServices"
        class="org.springframework.security.web.authentication.rememberme.PersistentTokenBasedRememberMeServices">
        <beans:constructor-arg value="key" />
        <beans:constructor-arg ref="userDetailsService" />
        <beans:constructor-arg ref="tokenRepository" />
        <beans:property name="tokenValiditySeconds" value="604800" />
    </beans:bean>

    <beans:bean id="tokenRepository"
        class="org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl">
        <beans:property name="dataSource" ref="dataSourceMysql" />
        <!-- <beans:property name="createTableOnStartup" value="true"/> --> <!-- 是否在系统启动时创建持久化token的数据库表 -->
    </beans:bean>

    <beans:bean id="rememberMeAuthenticationProvider"
        class="org.springframework.security.authentication.RememberMeAuthenticationProvider">
        <beans:constructor-arg value="key" />
    </beans:bean>
    <!--remember-me拦截器 end -->
    <!--登出拦截器 -->
    <beans:bean id="logoutFilter"
        class="org.springframework.security.web.authentication.logout.LogoutFilter">
        <beans:constructor-arg value="/admin/unlogin.html?logout=true" />
        <beans:property name="filterProcessesUrl" value="/j_spring_security_logout" />
        <beans:constructor-arg>
            <beans:list>
                <beans:ref bean="rememberMeServices" />
                <beans:bean
                    class="org.springframework.security.web.csrf.CsrfLogoutHandler">
                    <beans:constructor-arg ref="csrfTokenRepository" />
                </beans:bean>
                <beans:bean
                    class="org.springframework.security.web.authentication.logout.CookieClearingLogoutHandler">
                    <beans:constructor-arg index="0">
                        <beans:array>
                            <beans:value>JSESSIONID</beans:value>
                            <beans:value>remember-me</beans:value>
                        </beans:array>
                    </beans:constructor-arg>
                </beans:bean>
                <beans:bean
                    class="org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler" />
            </beans:list>
        </beans:constructor-arg>
    </beans:bean>
    <beans:bean id="csrfTokenRepository"
        class="org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository" />



    <!-- session 控制 -->
    <beans:bean id="concurrencyFilter"
        class="pn.empire.security.filter.ConcurrentSessionFilter">
        <beans:constructor-arg ref="sessionRegistry" />
        <beans:constructor-arg value="/static/406.html" />
    </beans:bean>
    <beans:bean id="sessionAuthenticationStrategy"
        class="org.springframework.security.web.authentication.session.CompositeSessionAuthenticationStrategy">
        <beans:constructor-arg>
            <beans:list>
                <beans:bean
                    class="org.springframework.security.web.authentication.session.ConcurrentSessionControlAuthenticationStrategy">
                    <beans:constructor-arg ref="sessionRegistry" />
                    <beans:property name="maximumSessions" value="1" />
                    <beans:property name="exceptionIfMaximumExceeded"
                        value="false" />
                </beans:bean>
                <beans:bean
                    class="org.springframework.security.web.authentication.session.SessionFixationProtectionStrategy" />
                <beans:bean
                    class="org.springframework.security.web.authentication.session.RegisterSessionAuthenticationStrategy">
                    <beans:constructor-arg ref="sessionRegistry" />
                </beans:bean>
            </beans:list>
        </beans:constructor-arg>
    </beans:bean>
    <beans:bean id="sessionRegistry"
        class="org.springframework.security.core.session.SessionRegistryImpl" />
    <!-- session 控制 end -->
    <!-- 一个自定义的filter,必须包含authenticationManager,accessDecisionManager,securityMetadataSource三个属性, 
        我们的所有控制将在这三个类中实现,解释详见具体配置 -->
    <beans:bean id="myFilter"
        class="pn.empire.security.filter.SecurityInterceptorFilter">
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <beans:property name="accessDecisionManager" ref="accessDecisionManager" />
        <beans:property name="securityMetadataSource" ref="securityMetadataSource" />
    </beans:bean>
    <beans:bean id="authSuccess"
        class="pn.empire.security.handler.AuthenticationSuccessHandler" />
    <beans:bean id="logoutSuccessHandler"
        class="pn.empire.security.handler.LogoutSuccessHandler" />
    <!-- 验证配置 , 认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 -->
    <authentication-manager alias="authenticationManager"
        erase-credentials="false">
        <authentication-provider user-service-ref="userDetailsService">
            <!-- 登入 密码 采用MD5加密 -->
            <password-encoder ref="passwordEncoder"/>
        </authentication-provider>
        <authentication-provider ref="rememberMeAuthenticationProvider" />
    </authentication-manager>
    <beans:bean id="passwordEncoder" class="pn.empire.security.handler.PwdEncodeHandler" />
    <!-- 项目实现的用户查询服务,将用户信息查询出来 -->
    <beans:bean id="userDetailsService"
        class="pn.empire.security.service.impl.UserDetailServiceImpl" />
    <!-- 访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源 -->
    <beans:bean id="accessDecisionManager"
        class="pn.empire.security.service.impl.AccessDecisionManager" />
    <!-- 资源源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色访问 -->
    <beans:bean id="securityMetadataSource"
        class="pn.empire.security.service.impl.InvocationSecurityMetadataSource" />

    <beans:bean id="messageSource"
        class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
        <beans:property name="basename"
            value="classpath:org/springframework/security/messages_zh_CN" />
    </beans:bean>
    <beans:bean id="authenticationEntryPoint"
        class="pn.empire.security.service.impl.AuthenticationEntryPoint">
        <beans:constructor-arg name="loginFormUrl"
            value="/admin/unlogin.html?entrypoint" />
    </beans:bean>
    <!-- 验证ajax请求 -->
    <beans:bean id="ajaxLoginFilter"
        class="pn.empire.security.filter.UsernamePasswordFilter">
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <beans:property name="authenticationFailureHandler"
            ref="ajaxFailureHandler" />
        <beans:property name="authenticationSuccessHandler"
            ref="ajaxSuccessHandler" />
        <beans:property name="filterProcessesUrl" value="/ajaxLoginProcess" />
        <beans:property name="sessionAuthenticationStrategy"
            ref="sessionAuthenticationStrategy" />
    </beans:bean>
    <beans:bean id="ajaxFailureHandler"
        class="pn.empire.security.handler.AjaxAuthenticationFailureHandler">
    </beans:bean>
    <beans:bean id="ajaxSuccessHandler"
        class="pn.empire.security.handler.AjaxAuthenticationSuccessHandler">
    </beans:bean>
    <!-- 验证admin ajax请求 -->
    <beans:bean id="adminAjaxLoginFilter"
        class="pn.empire.security.filter.UsernamePasswordFilter">
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <beans:property name="authenticationFailureHandler"
            ref="adminAjaxFailureHandler" />
        <beans:property name="authenticationSuccessHandler"
            ref="adminAjaxSuccessHandler" />
        <beans:property name="filterProcessesUrl" value="/adminAjaxLoginProcess" />
        <beans:property name="sessionAuthenticationStrategy"
            ref="sessionAuthenticationStrategy" />
        <beans:property name="rememberMeServices" ref="rememberMeServices" />
    </beans:bean>
    <beans:bean id="adminAjaxFailureHandler"
        class="pn.empire.security.handler.AdminAjaxAuthenticationFailureHandler">
    </beans:bean>
    <beans:bean id="adminAjaxSuccessHandler"
        class="pn.empire.security.handler.AdminAjaxAuthenticationSuccessHandler">
    </beans:bean>
    <!-- 验证普通用户 -->
    <beans:bean id="loginFilter"
        class="pn.empire.security.filter.UsernamePasswordFilter">
        <beans:property name="authenticationManager" ref="authenticationManager" />
        <beans:property name="authenticationFailureHandler"
            ref="failureHandler" />
        <beans:property name="authenticationSuccessHandler"
            ref="authSuccess" /> <!-- ref="successHandler"/> -->
        <beans:property name="filterProcessesUrl" value="/loginProcess" />
        <beans:property name="sessionAuthenticationStrategy"
            ref="sessionAuthenticationStrategy" />
    </beans:bean>

    <beans:bean id="failureHandler"
        class="org.springframework.security.web.authentication.SimpleUrlAuthenticationFailureHandler">
        <beans:property name="defaultFailureUrl" value="/admin/login.html?login_error=1" />
    </beans:bean>

    <beans:bean id="successHandler"
        class="org.springframework.security.web.authentication.SavedRequestAwareAuthenticationSuccessHandler">
        <beans:property name="alwaysUseDefaultTargetUrl" value="false" />
        <beans:property name="defaultTargetUrl" value="/" />
    </beans:bean>
    <beans:bean id="httpSessionRequestCache"
        class="org.springframework.security.web.savedrequest.HttpSessionRequestCache">
    </beans:bean>
</beans:beans>

首先来说http配置:
1.use-expressions:是否启用intercept-url元素的access属性对Spring EL表达式的支持,但是在配置中并没有使用到。
2.auto-config:是否启用默认配置,在配置中设置为false,基本都采用自定义配置。

  1. entry-point-ref:第三方登录入口,认证不通过则抛出一个异常给ExceptionTranslationFilter,由它进行通过entry-point-ref设置的入口点进行处理,通过此配置可以重定向到其他页面。
    4.authentication-manager-ref:引用的AuthenticationManager,指定身份验证bean,我觉得可以算作核心了。
    5.session过滤器,代码如下:
  <custom-filter position="CONCURRENT_SESSION_FILTER" ref="concurrencyFilter" />

主要功能为当用户session过期用户却继续访问时,系统会跳转至指定路径。
6.access-denied-handler:访问失败才会进AccessDeniedHandler,如果是未登录或者会话超时等,不会触发AccessDeniedHandler,而是会直接跳转到登录页面
7.custom-filter:自定义登录登出记住我过滤器。
8.开启csrf,csrf生成的token是存储在cookies中,防止跨域攻击,所以并不能防止重复提交。
9.为了页面中可以使用iframe,配置header:

<headers>
            <frame-options policy="SAMEORIGIN"></frame-options>
</headers>

下面说一下注册的bean
1.csrfSecurityRequestMatcher:这个bean控制了那些路径不需要csrf限制,比如说一些接口、富文本编辑之类。

    private Pattern allowedMethods = Pattern.compile("^(GET|HEAD|TRACE|OPTIONS)$");
    private RegexRequestMatcher unprotectedMatcher = new RegexRequestMatcher("/unprotected", null);
    @Override
    public boolean matches(HttpServletRequest request) {
        if (execludeUrls != null && execludeUrls.size() > 0) {
            String servletPath = request.getServletPath();
            for (String url : execludeUrls) {
                if (servletPath.contains(url)) {
                    return false;
                }
            }
        }
        if (allowedMethods.matcher(request.getMethod()).matches()) {
            return false;
        }
        return !unprotectedMatcher.matches(request);
    }

可以看一下代码,除了指定路径外,还对GET、HEAD、TRACE、OPTIONS免除了csrf过滤,主要是针对post请求进行过滤。

2.accessDeniedHandler:访问失败才会进AccessDeniedHandler,如果是未登录或者会话超时等,不会触发AccessDeniedHandler,而是会直接跳转到登录页面。
3.rememberMeFilter:配置的记住我过滤器,注入身份验证bean以及rememberMeServices。
4.rememberMeServices:注入userDetailsService和token存储。
5.tokenRepository:token处理方式,在配置中选择在数据库中进行存储
6.rememberMeAuthenticationProvider:token的处理类,key要一致,官方说明如下:

This implementation supports the simpler approach described in [Section 18.2, “Simple Hash-Based Token Approach”](https://docs.spring.io/spring-security/site/docs/5.0.0.RELEASE/reference/htmlsingle/#remember-me-hash-token "18.2 Simple Hash-Based Token Approach"). `TokenBasedRememberMeServices` generates a `RememberMeAuthenticationToken`, which is processed by `RememberMeAuthenticationProvider`. A `key` is shared between this authentication provider and the `TokenBasedRememberMeServices`. In addition, `TokenBasedRememberMeServices` requires A UserDetailsService from which it can retrieve the username and password for signature comparison purposes, and generate the `RememberMeAuthenticationToken` to contain the correct `GrantedAuthority` s. Some sort of logout command should be provided by the application that invalidates the cookie if the user requests this. `TokenBasedRememberMeServices` also implements Spring Security’s `LogoutHandler` interface so can be used with `LogoutFilter` to have the cookie cleared automatically.

The beans required in an application context to enable remember-me services are as follows:

<pre class="programlisting" style="line-height: 1.4; color: black; font-size: 15px; padding: 6px 10px; background-color: rgb(248, 248, 248); border: 1px solid rgb(204, 204, 204); border-radius: 3px; clear: both; overflow: auto; font-family: Consolas, &quot;Liberation Mono&quot;, Courier, monospace; font-style: normal; font-variant-ligatures: normal; font-variant-caps: normal; font-weight: 400; letter-spacing: normal; orphans: 2; text-align: start; text-indent: 0px; text-transform: none; widows: 2; word-spacing: 0px; -webkit-text-stroke-width: 0px; text-decoration-style: initial; text-decoration-color: initial;"><bean id="rememberMeFilter" class=
"org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter">
<property name="rememberMeServices" ref="rememberMeServices"/>
<property name="authenticationManager" ref="theAuthenticationManager" />
</bean>

<bean id="rememberMeServices" class=
"org.springframework.security.web.authentication.rememberme.TokenBasedRememberMeServices">
<property name="userDetailsService" ref="myUserDetailsService"/>
<property name="key" value="springRocks"/>
</bean>

<bean id="rememberMeAuthenticationProvider" class=
"org.springframework.security.authentication.RememberMeAuthenticationProvider">
<property name="key" value="springRocks"/>
</bean></pre>

Don’t forget to add your `RememberMeServices` implementation to your `UsernamePasswordAuthenticationFilter.setRememberMeServices()` property, include the `RememberMeAuthenticationProvider` in your `AuthenticationManager.setProviders()` list, and add `RememberMeAuthenticationFilter` into your `FilterChainProxy` (typically immediately after your `UsernamePasswordAuthenticationFilter`).

7.logoutFilter:自定义登出过滤器,之所以配置这么复杂是为了配合remember-me功能、以及用户只能在一处登录的功能、csrf过滤用能使用。
8.csrfTokenRepository:csrfToken仓库,用户访问后会生成csrf token存在用户浏览器的cookies中,会对用户每次符合验证规则的请求进行token校验,防止跨域攻击,但是不能防止重复提交。在一个会话中,token是一致的。
9.myFilter:继承AbstractSecurityInterceptor,负责处理HTTP资源的安全性。整个过程需要依赖AuthenticationManager、AccessDecisionManager和FilterInvocationSecurityMetadataSource。
10.authSuccess:自定义的表单登录成功处理器。
11.logoutSuccessHandler:登出成功处理器
12.authenticationManager:用户信息认证管理器。
13.passwordEncoder:根据自定义加密方式进行比对
14.userDetailsService:自定义用户信息类。
15.accessDecisionManager:访问决策器,定义了资源可以被哪些角色访问。
16.securityMetadataSource:资源-角色对应关系。
17.messageSource:security的国际化加载
18.authenticationEntryPoint:第三方登录入口,自定义该bean主要是为了ajax登录。
19.ajaxLoginFilter:ajax登录过滤器。
20.ajaxFailureHandler:ajax登录失败处理器
21.ajaxSuccessHandler:ajax登录成功处理器
下面就类似了,当初定义了三个登录不同的界面,所以写才的如此麻烦。
httpSessionRequestCache:可以理解为缓存控制。



作者:Mr_加菲
链接:https://www.jianshu.com/p/8a1312c7b1d0
來源:简书
简书著作权归作者所有,任何形式的转载都请联系作者获得授权并注明出处。

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值