使用spring-security模块
1. Maven依赖和版本
2. 配置xml和对象
2.1. 配置ldap
2.2. 配置登录后处理
2.3 配置过滤器
3. 重定向和反向代理
4. Cookie的path设置
5. 配置过程中遇到的问题
1. Maven的依赖和版本
在引入spring-security依赖时.最开始使用的4.1.1.RELEASE,SPRING使用的4.2.6.RELEASE,结果一直报有对象找不到.后来改成spring-security.4.0.3.RELEASE后解决.最后springframework使用的4.2.6.RELEASE,spring-security使用的4.0.3.RELEASE.
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-webartifactId>
<version>${spring-security.version}version>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-configartifactId>
<version>${spring-security.version}version>
dependency>
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-ldapartifactId>
<version>${spring-security.version}version>
dependency>
2. application-security.xml配置
xmlns:s="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beanshttp://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/securityhttp://www.springframework.org/schema/security/spring-security.xsd "> 2.1 ldap配置 3. 重定向和反向代理 在使用中,由于我们的项目是使用的前后端分离,后端是有多个application的.所以在认证所在app里重定向相对地址会变成http://xxx/projectName/index.html.这样就不能访问到真的t.html(正确地址应该是http://xxx/index.html).而如果写全地址,则以后域名更改后又要改代码,会比较麻烦.我们项目是使用的apache.所以通过apache的反向代理来进行网址的转化.原来是这么配置的 ProxyPassReverse /xx http://127.0.0.1:8680/xx 改为 ProxyPassReverse / http://127.0.0.1:8680/配置ldap验证登录.首先需要配置org.springframework.security.ldap.DefaultSpringSecurityContextSource
, 在构造方法里配置ldap连接,然后注入userDn,password两个值,即连接的用户名和密码.这里既可以使用上面的contextSource,也可以使用org.springframework.ldap.core.support.LdapContextSource ,两个配置contextSource的类都可以.
接下把contextSource注入ldapProvider的构造方法里.同时要传入属性值userSearch.userSearch是登录验证时,如何查询用户的.在这里要规定查询范围. org.springframework.security.ldap.search.FilterBasedLdapUserSearch 构造函数需要传入三个参数:0-查询基础(确定在什么范围查找),1-查询过滤字段(根据什么字段查找),2-contextSource(用来建立ldap连接).配置完ldap相关内容后将ldapprovider 注入authentication-manager中.
这里提一下ldap中的一些属性.CN ( Common Name ),OU (Organizational Unit),DC(Domain Component)都是ldap服务器中区别名称DN ( distinguished name )
例如:CN=test,OU=developer,DC=domainname,DC=com
在上面的代码中 cn=test 可能代表一个用户名,ou=developer 代表一个 active directory 中的组织单位。这句话的含义可能就是说明 test 这个对象处在domainname.com 域的 developer 组织单元中.
2.2 配置登录后处理
刚刚配置了如何认证用户,现在配置哪些需要认证.
在http元素里配置需要认证的接口.
intecept-url里写上pattern以及access级别,需要认证的是authenticated,不需要的是permitAll. entry-point-ref是认证失败后的操作(实现AuthenticationEntryPoint接口的 commence方法,restful接口返回401,访问页面则跳转到登录页面).
form-login提供表单登录页,访问xx/login就能看到. default-target-url是认证成功默认跳转地址.authentication-success-handler-ref是登录成功的方法(这里重写SimpleUrlAuthenticationSuccessHandler的onAuthenticationSuccess方法来定制认证成功后的操作),使用SimpleUrlAuthenticationSuccessHandler,则之前的default-target-url的地址就失效了, authentication-failure-handler-ref是登录失败的方法,使用SimpleUrlAuthenticationFailureHandler.
public class RestAuthenticationSuccessHandler extends SimpleUrlAuthenticationSuccessHandler
{
private RequestCache requestCache = new HttpSessionRequestCache();
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException
{
final SavedRequest savedRequest = requestCache.getRequest(request,response);
//第一次访问
if(savedRequest == null)
{
clearAuthenticationAttributes(request);
response.sendRedirect("/t.html");
return;
}
final String targetUrlParameter = getTargetUrlParameter();
if(isAlwaysUseDefaultTargetUrl()|| (targetUrlParameter!=null&& StringUtils.hasText(request.getParameter(targetUrlParameter))))
{
requestCache.removeRequest(request,response);
clearAuthenticationAttributes(request);
return;
}
clearAuthenticationAttributes(request);
// Use the DefaultSavedRequest URL
final String targetUrl = savedRequest.getRedirectUrl();
logger.debug("Redirecting to DefaultSavedRequest Url: " + targetUrl);
// getRedirectStrategy().sendRedirect(request, response, targetUrl);
response.sendRedirect(targetUrl);
}
public void setRequestCache(RequestCache requestCache) {
this.
requestCache = requestCache; }}
public class RestAuthenticationEntryPoint implements AuthenticationEntryPoint
{
public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException
{ /*if ajax request return 401 Unauthorized
else rediect to specific page
*/
if("XMLHttpRequest".equals(httpServletRequest.getHeader("x-requested-with")))
httpServletResponse.sendError(HttpServletResponse.SC_UNAUTHORIZED,"Unauthorized");
else
httpServletResponse.sendRedirect("/xx/login");
}
}
2.3 配置过滤器
最后在web.xml里配置过滤器
<filter>
<filter-name>springSecurityFilterChainfilter-name>
<filter-class>org.springframework.web.filter.DelegatingFilterProxyfilter-class>
filter>
<filter-mapping>
<filter-name>springSecurityFilterChainfilter-name>
<url-pattern>/*url-pattern>
filter-mapping>
以上这些配置完后就可以使用spring-security的认证功能了.
4. Cookie的path配置
同上的原因,所以认证生成的cookie的path是/xx,也就是在其他页面无效,只能在http://localhost/xx下有效.cookie的作用域是由应用容器决定的,这方面spring好像不大好改.所以要改web.xml将path变成全局的.如下:
<session-config>
<cookie-config>
<path>/path>
cookie-config>
session-config>
5. 配置过程中遇到的问题
其实在配置过程中碰到需要报错,没能一一记下,但是晃晃悠悠也都解决或者避过去了.很多问题之前都遇到过,但是身处山中不知山,在面对没接触的东西的时候,会有怕麻烦和未知的恐惧,所以很多本来应该能看出来的问题也兜了一些圈子.
404 pageNotFound 这就是Controller里没有这个mapping,没有其他原因,具体是名字写错了,还是没有被注入applicationContext都有可能.遇到这个问题直接找spring加载初始化的问题,和spring-security无关.
302 Found 这是ajax请求遇到重定向页面报的错.如果是页面访问,它会正常重定向到目标页面.但是ajax访问会返回成功码302,还有重定向的页面内容.这里提一句,一般jquery的ajax请求会在header多一个属性x-requested-with: XMLHttpRequest可以通过这个来区别ajax和普通请求.
重定向时 spring-web的DefaultRedirectStrategy重定向相对地址会给路径中间加上项目名,HttpServletRequest的重定向则不会