SpringSecurity⼊门详解
序:本⽂主要参考 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过滤器提供各种各样的安全性功能.这也需要在l中配置⼀系列相关的<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>
<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 分散式⽤户⾝份识别系统
springmvc常用标签中⼼认证服务(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>

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。