Spring框架:Spring安全

在传统的Web发展,安全码被分散在各个模块,这样方便管理,有时你可能会错过一个地方导致安全漏洞。为了解决这个问题,它的发明Spring Security。它是业务逻辑的有关安全代码的作用全部转移到一个集中管理模块。实质上AOP一个子集。


过滤URL

为了过滤URL,首先要在web.xml中增加一个过滤器。filter-name不能随便填写,由于它和另外一个bean的名称是一样的。

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


以下配置的作用是拦截全部的请求。

<security:http auto-config="true">
  <intercept-url pattern="/**" access="ROLE_VIP"/>
</security:http>
auto-config的作用相当于<form-login/><http-basic/><logout/>,它会给你自己主动生成一个登陆页面。access="ROLE_VIP"表示仅仅连接身份为ROLE_VIP的用户,ROLE_VIP这个名称是由我们自定义的。


上面的样例中,Spring框架自己主动生成了一个登陆页面。可是不太美观。

因此,我们须要自定义登陆页面。

<http auto-config="true">
  <form-login login-processing-url="/static/j_spring_security_check" login-page="/login" authentication-failure-url="/login?

login_error=t"/> </http>


自己定义的登陆页面代码例如以下。表单中的j_username、j_password、_spring_security_remember_me这几个名字是框架已经定死的。自己不能任意修改。
<spring:url var="authUrl" value="/static/j_spring_security_check"/>
<form method="post" action="${authUrl}">
  <input name="j_username" type="text"/>
  <input name="j_password" type="password"/>
  <input name="_spring_security_remember_me" type="checkbox"/>
  <input type="submit"/>
</form>


认证表达式。上面的样例中使用了access="ROLE_VIP"限制了VIP用户的訪问,这还不够,你能够在access中填写复杂的Spring表达式实现更强大的功能。比方以下的样例:
<http auto-config="true" use-expressions="true">
  <intercept-url pattern="/admin/**" access="hasRole('ROLE_ADMIN') and hasIpAddress('192.168.1.2')"/>
</http>

注意一定要开启use-expression=true。


认证表达式中支持的函数有:denyAll、hasAnyRole、hasRole、hasIpAddress、isAnonymouse、isAuthenticated、isFullyAuthenticated、isRememberMe、permitAll。支持的变量有autentication、principal。


HTTPS拦截。有些特殊的URL必需要用HTTPS安全连接。

写法例如以下。

<intercept-url pattern="/admin" requires-channel="https"/>
<intercept-url pattern="/public" requires-channel="http"/>


保护视图

在JSP文件訪问与认证有关的变量。或者依据訪问者的身份显示不同的内容。


訪问认证细节。比方訪问登陆的username。

<sec:authentication property="principal.username"/>


依据不同的身份显示不同的内容。请看以下的样例。

<sec:authorize access="hasRole('ROLE_VIP')">
  You are VIP.
</sec:authorize>


认证方式

Spring支持的认证方式有:基于xml配置、基于JDBC、基于LDAP、OpenID、CAS、X509、JAAS。


基于xml配置。将username和password写在配置文件里。

<security:user-service id="userService">
  <user name="root" password="123456" authorities="ROLE_VIP,ROLE_ADMIN"/>
  <user name="test" password="test" authorities="ROLE_VIP"/>
</security:user-service>

<security:authentication-manager>
  <authentication-provider user-service-ref="userService"/>
</security:authentication-manager>


基于JDBC。

<security:jdbc-user-service id="userService" data-source-ref="dataSource" users-by-username-query="select username,password,enabled from user where username=?" authorities-by-username-query="select username,authoritiy from user_auth"/>


基于LDAP。

<security:authentication-manager alias="authenticationManager">
  <security:ldap-authentication-provider user-search-filter="(uid={0})" group-search-filter="member={0}">
    <security:password-compare hash="md5"/>
    
    <security:ldap-server url="ldap://example.com/dc=test"/>
  </security:ldap-authentication-provider>
</security:authentication-manager>


记住登陆

<http auto-config="true">
  <remember-me key="myVipKey" token-validity-seconds="86400"/>
</http>

myVipKey是Cookie中的令牌键名,令牌中保存了过期时间、username、令牌密钥。


拦截方法调用

开启注解方式的安全拦截。

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


依据身份进行拦截。

@Secured("ROLE_VIP")
public void test(){}


过滤返回值。

@PostFilter("filterObject.user.username == principal.name")
public List<User> getUserList(){}


横切授权

<global-method-security>
  <protect-pointcut access="ROLE_VIP" expression="execution(@com.example.User * *.*(String))"/>
</global-method-security>

版权声明:本文博客原创文章,博客,未经同意,不得转载。

原文地址:https://www.cnblogs.com/gcczhongduan/p/4633123.html