这里写目录标题
- Spring Security简单介绍及常用配置
- 介绍
- 执行流程
- 执行流程图
- 加密和解密
- xml配置实现访问权限控制
Spring Security简单介绍及常用配置
介绍
spring security作为spring旗下的功能模块,它是一个功能强大且高度可定制的身份验证和访问控制框架。它是用于保护基于Spring的应用程序的实际标准。
总的来说就是为了给项目提供身份验证和授权,防止攻击,并且对Servlet API进行了集成。并且拥有高度可扩展性,满足自定义需求。
身份验证: 对用户身份进行校验,如果确实存在此用户,则可以进行放行,如果不存在此用户,则给予拦截,不许放行。
授权: 对登录成功的用户进行鉴权,保证用户只能访问在自己权利之内的接口,实现权限划分。
spring security是通过过滤器链和xml配置解析或通过权限提供类对身份进行拦截和身份校验,同时基于对cookie和session的操作来实现身份验证。并且可以通过注解装配来实现接口的访问控制。
执行流程
- 首先要在web.xml中配置DelegatingFilterProxy过滤器,这个类用于代理所有第三方的安全框架,我们不但可以使用spring security,同时也可以使用其他第三方安全框架,比如apache旗下的shiro。在这里我们还是使用Spring Security框架。所以过滤器的名字必须要叫springSecurityFilterChain(注:如果使用Spring Security那么这个名字是固定的,不可自己指定)
- 当用户发起请求的时候会被AuthenticationProcessingFilter拦截,并且调用AuthenticationManager的实现,通过调用ProviderManager来获取用户验证信息。我们可以通过xml配置,或者是通过自定义类来继承UserDetailsService接口,并实现loadUserByUsername()方法。通过这个方法连接数据库,获取用户验证信息。如果验证通过,则会将用户信息和权限信息封装成一个User类放入SecurityContextHolder中,如果后面要使用这个信息,同样可以通过SecurityContextHolder来获取当前登录用户信息。
- 当用户访问url时,会通过AbstractSecurityInterceptor拦截器进行拦截,其中调用FilterInvocationSecurityMetadataSource来获取访问这个url所需要的权限,在调用AccessDecisionManager通过SecurityContextHolder获取当前用户所拥有的的权限信息,如果用户拥有权限,则放行,如果权限不足,则抛出异常。
执行流程图
加密和解密
为了保证用户密码不会被泄露,通常会采用加密方式对用户密码进行加密。spring security也拥有解密的相关机制,我们可以指定在进行密码校验时使用哪种解密规则。
spring security也为我们提供了一个加密方式BCryptPasswordEncoder,只需要将这个对象配置给ProviderManager,spring security就会自动使用这个加密方式帮我们对登录密码进行这个方式的解密认证。
我们也可以自己实现一个加密方式,只需要一个自定义类,并实现PasswordEncoder接口。将自定义类交给ProviderManager就会按照自己制定的加密方式进行解密。
xml配置实现访问权限控制
因为spring security是spring公司的,可以直接在spring配置文件中进行配置。
下面简单介绍一下关于spring security的常用标签
标签 | 说明 |
<security:http> | 配置资源访问,auto-config=“true"表示使用默认配置,use-expressions=“true” 表示使用权限表达式,security=“none” 设置为匿名访问, pattern=”/login.html" 设置匿名访问的页面 |
<security:global-method-security> | pre-post-annotations=“enabled” 属性用于配置方法上的权限锁定注解 |
<security:authentication-manager> | 权限认证管理器 |
<security:authentication-provider> | 权限提供者 user-service-ref="springSecurityUserService"属性可以指定使用哪个方法提供用户信息 |
<security:user-service> | 配置用户服务 |
<security:user> | 具体用户信息 |
<security:headers> | 安全性配置 |
<security:frame-options> | 安全级别,policy=“SAMEORIGIN” 表示允许同源访问 |
<security:intercept-url> | 拦截地址,pattern="/pages/**" 表示拦截地址 access="isAuthenticated()"表示认证通过即可访问,也可以配置其他角色或者权限,意为拥有此角色或此权限才可访问 |
<security:form-login> | 登录页面配置 login-page="/login.html" 表示登录页面地址,username-parameter=“username” 设置账号字段,password-parameter=“password” 设置密码字段,default-target-url="/pages/main.html" 设置成功后跳转的页面地址,authentication-failure-url="/login.html" 设置登录失败后跳转的地址,login-processing-url="/login.do"设置登录请求字段 |
<security:logout> | 退出配置,logout-url="/logout.do" 设置退出请求字段,logout-success-url="/login.html" 设置退出成功后跳转页面地址,invalidate-session=“true” 设置清除session域 |
<security:csrf> | 配置csrf,disabled=“true” 表示禁用csrf,配置这个后才可以使用自定义登录界面 |
具体xml配置
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:security="http://www.springframework.org/schema/security"
xmlns:context="http://www.springframework.org/schema/context"
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 http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
<!--开启注解权限控制-->
<security:global-method-security pre-post-annotations="enabled"/>
<!--配置公共资源-->
<security:http security="none" pattern="/login.html"/>
<security:http security="none" pattern="/css/**"/>
<security:http security="none" pattern="/img/**"/>
<security:http security="none" pattern="/js/**"/>
<security:http security="none" pattern="/plugins/**"/>
<!--配置访问设置-->
<security:http auto-config="true" use-expressions="true">
<!--允许iframe页面嵌套-->
<security:headers>
<security:frame-options policy="SAMEORIGIN"/>
</security:headers>
<!--认证通过即可访问-->
<security:intercept-url pattern="/pages/**" access="isAuthenticated()"/>
<!--登录页面设置-->
<security:form-login login-page="/login.html"
username-parameter="username"
password-parameter="password"
default-target-url="/pages/main.html"
authentication-failure-url="/login.html"
login-processing-url="/login.do"/>
<!--退出设置-->
<security:logout logout-url="/logout.do"
logout-success-url="/login.html"
invalidate-session="true"/>
<!--控制一个账号最多只有一个人访问-->
<security:session-management>
<security:concurrency-control max-sessions="1" error-if-maximum-exceeded="false"/>
</security:session-management>
<!--禁用scrf-->
<security:csrf disabled="true"/>
</security:http>
<!--配置认证管理器-->
<security:authentication-manager>
<!--配置权限提供者-->
<security:authentication-provider user-service-ref="springSecurityUserService">
<security:password-encoder ref="passwordEncoder"/>
</security:authentication-provider>
</security:authentication-manager>
<!--配置加密对象-->
<bean id="passwordEncoder" class="org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder"/>
</beans>
在权限提供者里,springSecurityUserService类是一个自定义类,实现了UserDetailsService接口,通过实现这个接口,将这个实现类交给spring管理,spring会自动通过这个类去获取用户信息,具体方法内部怎么获取用户信息,还要靠自己去实现。
在接口访问的权限控制中,我们使用注解方式去实现
我们可以在Controller层的方法上加上@PreAuthorize()注解,用于在访问这个接口前进行角色校验或权限校验,里面的值为字符串,和配置里的表达式相同,可以通过@PreAuthorize(“hasAuthority(’<具体权限名>’)”)指定哪个权限可以使用这个接口,也可以通过@PreAuthorize(“hasRole(’<具体角色>’)”)指定哪个角色可以使用这个接口。