今天继续聊SpringSecurity,说明一下下面所有的聊天内容都基本是以前面的为基础,所以有兴趣的同学不要跳跃,以免有所遗漏。昨天的一聊中我们只是简简单单的搭建起来了一个SpringSecurity的入门案例。这个案例根本满足不了我们日常的研发需要,所以我们必须深度的对SpringSecurity的探究一下。以昨天的为基础:昨天的是利用SpringSecurity自带的登录页面进行登录,今天探究自定义登录页面进登录。
第一步:将HelloController改为SpringSecurityController。这个修改是我自己想改的见名知意一点,你不该也行。
第二步:添加专门用于页面跳转的Controller:SpringSecurityPageController代码如下:
package com.alibaba;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.servlet.ModelAndView;
@Controller
@RequestMapping(value="/SpringSecurityPageController")
public class SpringSecurityPageController {
/**
* 用户登录时的页面
* @return
*/
@RequestMapping(value="/gotoUserLoginPageJsp",method = RequestMethod.GET)
public ModelAndView gotoUserLoginPageJsp(@RequestParam(value = "error",required = false)String error) {
try {
System.out.println("-----" + error);
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("description", "输入用户名和密码进行登录");
modelAndView.setViewName("userLogin");
return modelAndView;
}
catch (Exception e) {
System.out.println("SpringSecurityPageController/toUserLoginPageJsp Exception:" + e.getMessage());
return null;
}
}
/**
* 用户登录成功以后的页面
*/
@RequestMapping(value="/toUserWelComePageJsp",method = RequestMethod.GET)
public ModelAndView toUserWelComePageJsp() {
try {
ModelAndView modelAndView = new ModelAndView();
modelAndView.addObject("description", "登录成功");
modelAndView.setViewName("userWelCome");
return modelAndView;
}
catch (Exception e) {
System.out.println("SpringSecurityPageController/toUserLoginPageJsp Exception:" + e.getMessage());
return null;
}
}
}
第三步:修改springsecurity.xml的配置:
<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-3.0.xsd
http://www.springframework.org/schema/security
http://www.springframework.org/schema/security/spring-security-3.2.xsd">
<!--
配置具体的规则:
auto-config="true" 不用自己编写登录的页面,框架提供默认登录页面
use-expressions="false" 是否使用SPEL表达式(没学习过)
-->
<beans:bean id="failureCDW" class="com.alibaba.failureCDW"></beans:bean>
<http auto-config="false" use-expressions="false">
<!--配置具体拦截的url,pattern是拦截的url,access是访问被拦截的url需要的权限-->
<intercept-url pattern="/*" access="ROLE_USER" />
<intercept-url pattern="/**/to**" access="ROLE_USER" />
<intercept-url pattern="/**/gotoUserLoginPageJsp" access="IS_AUTHENTICATED_ANONYMOUSLY" />
<!-- 定义跳转的具体页面
form-login是spring security命名空间配置登录相关信息的标签,它包含如下属性:
1. login-page 自定义登录页url,默认为/login
2. login-processing-url 登录请求拦截的url,也就是form表单提交时指定的action
3. default-target-url 默认登录成功后跳转的url
4. always-use-default-target 是否总是使用默认的登录成功后跳转url
5. authentication-failure-url 登录失败后跳转的url
6. username-parameter 用户名的请求字段 默认为userName
7. password-parameter 密码的请求字段 默认为password
8. authentication-success-handler-ref 指向一个
AuthenticationSuccessHandler用于处理认证成功的请求,不能和default-target-url
还有always-use-default-target同时使用
9. authentication-success-forward-url 用于authentication-failure-handler-ref
10. authentication-failure-handler-ref 指向一个AuthenticationFailureHandler用于处理失败的认证请求
11. authentication-failure-forward-url 用于authentication-failure-handler-ref
12. authentication-details-source-ref 指向一个AuthenticationDetailsSource,在认证过滤器中使用
-->
<form-login
login-page="/SpringSecurityPageController/gotoUserLoginPageJsp.do"
default-target-url="/SpringSecurityPageController/toUserWelComePageJsp.do"
authentication-failure-url="/SpringSecurityPageController/gotoUserLoginPageJsp.do?error=error"
always-use-default-target="true"
username-parameter="username"
password-parameter="password" />
<logout logout-success-url="/login?logout" />
<!--关闭跨域请求,不关闭就会拦截所有的访问,显示权限不够-->
<csrf />
</http>
<authentication-manager>
<authentication-provider>
<user-service>
<user name="chendawei" password="123456" authorities="ROLE_USER"/>
</user-service>
</authentication-provider>
</authentication-manager>
</beans:beans>
第四步: 创建用户登录的界面:userLogin.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>userLogin</title>
</head>
<body οnlοad='document.aa.username.focus();'>
${description}
<form name="aa" action="/SecurityLogin/<c:url value='j_spring_security_check' />" method="POST">
用户名:<input type="text" name="username"/><br>
密码:<input type="text" name="password">
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
<input type="submit" value="登录">
</form>
</body>
</html>
第五步:创建用户登录成功以后欢迎的界面,userWelcome.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ page session="true"%>
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>userWelCome</title>
</head>
<body>
${description}
</body>
</html>
第六步:访问
直接访问登录成功以后的页面后,被重定向到登录接页面:
输入一个错误的用户名和密码,发现还是被重定向到登录界面,在后台可以看到打印出来了error标志,说明走的是登录失败以后的URL链接:
后台也答应出了error:
上面输入错误的以后,我们再输入一个正确的:
然后就可以正确跳转到欢迎页面了:我们再欢迎页面可以看到,验证成功无误以后重定向到欢迎页面了:
说一下在自定义登录页面时遇见的问题,这个是重点:
问题一:在输入正确的用户名和密码以后,也配置了验证成功以后要跳转的页面路径,但始终不能跳转一直回到登录界面:
问题产生的原因:
在于登录界面表单提交时<form>标签中action指定的路径或者配置文件中login-processing-url不正确。
解决办法:
如果在springsecurity.xml中<user>标签里提前配置了用户名和密码,那么可以将校验用户名和密码的任务交给SpringSecurity框架帮助我们验证。那么此时的action中的路径就不能瞎指定,必须指定为:/项目名称/<c:url value='j_spring_security_check' />其中j_spring_security_check是SpringSecurity默认的路径,于此同时在配置文件中就不需要指定login-processing-url属性了。好如果我们不需要SpringSecurity来帮助我们来做校验的话,那么就在ation中指定我们自己的路径,同时在springsecurity.xml配置文件中必须指定login-processing-url属性的值。注意此时login-processing-url属性的值必须要和action中的值一模一样。具体的指定规则是:action中是:/类名/方法名 ;login-processing-url中指定的是:/项目名/类名/方法名。总之两个地方的URL最终是要一样。
问题二:配置文件中authentication-failure-url已经指定了验证失败以后要跳转的路径或者页面,但是输入错误的用户名或密码后无法正常的跳转至认证失败的页面,一直在登录界面。
问题所在原因:
SpringSecurity框架因为自身的原因,它会默认的取登录链接为失败以后的跳转链接,所以这里无法跳转。
解决的办法:
authentication-failure-url的指定就指定为登录的链接过界面,但是在登录的链接中要加一个参数用于判断当前的链接是否为认证错误的链接。
问题三:在登录的界面如果没有<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>报403的页面错误提示信息为:Expected CSRF token not found. Has your session expired?
问题所在原因:这是SpringSrcurity框架在4.X以下版本时没有去解决csrf的问题,也就是没有去禁用csrf。我这里用的是3.2.3的版本所以就会出现。
解决的办法:在登录的表单中添加<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>。
问题四:<csrf disable="true"/>添加报错
问题所在原因:SpringSecurity框架版本的问题。
解决办法:选用4.X及以上的版本就可以了然后在配置文件中的scaham信息中将连接中的xsd版本改为对应jar包的版本。
至此我们基于配置文件的SpringSecurity的就聊完了,接下来我们聊聊去除SpringSecurity的注销登录。