在上一篇的基础上进行修改.
一.配置自定义登录.
如果没有指定一个登录页面,Spring Security默认将用户重定向到/spring_security_login。
然后o.s.s.web.filter.FilterChainProxy会选择o.s.s.web.authentication.ui.DefaultLoginPageGeneratingFilter,
它来渲染默认的登录页面。既然我们选择了覆盖默认的URL,我们自己负责生成登录页面。
login-processing-url属性默认为/ j_spring_security_check,它指定登录表单(其中应包括用户名和密码)应提交时,使用的HTTP POST的URL。
当spring security处理此请求时,它会尝试对用户进行认证.
username-parameter和password-parameter参数属性默认为j_username和j_password,分别指定处理登录时,Spring Security将用来认证用户的HTTP参数。
如果用户名和密码提交到登录处理页面是无效的,authentication-failure-url属性指定Spring Security会重定向的URL
用来显示失败登录原因.input names匹配上面的username-parameter和password-parameter
3.让spring mvc识别新的url请求,在src/main/java/com/packtpub/springsecurity/web/config/WebMvcConfig.
java添加如下代码:
1.在security.xml继续配置http元素,添加
logout-url指定登出的处理链接,默认是/j_spring_security_logout.实际上会被o.s.s.web.authentication.logout.LogoutFilter处理.
logout-success-url当然是成功登录后的跳转url
2.在src/main/webapp/WEB-INF/views/includes/header.jsp加上
在src/main/webapp/WEB-INF/views/login.jsp加上
登录页也无情,一样被拦,所以我们要排除登录和登出的页面被这配置拦截.在 <intercept-url pattern="/**" access="ROLE_USER"/>前面加上(为什么是前面就不必问了),
* 匹配0个或多个字符, 排除 /.
** 在一个路径匹配一个或多个目录.
4.重启jetty,发现可以正常登录了.
三.基于表达式的授权.使用了use-expressions设为true后,access配置就只能使用表达式语法了.permitAll还是一样能使用的.
例如像下面:
四.有条件地显示认证信息(指的是在jsp页面使用sec标签)
1.加入新依赖
可再次重启jetty测试了
五.登录后再想做些事情...即定义登录后的行为.
通过form-login元素的default-target-url属性,再在controller定义一个处理方法就OK了
一.配置自定义登录.
1.在http元素内加入
<form-login login-page="/login/form"
login-processing-url="/login"
username-parameter="username"
password-parameter="password"
authentication-failure-url="/login/form?error"/>
如果未通过身份验证的用户访问了受保护的页面,Spring Security将浏览器重定向到login-page属性指定的路径。
如果没有指定一个登录页面,Spring Security默认将用户重定向到/spring_security_login。
然后o.s.s.web.filter.FilterChainProxy会选择o.s.s.web.authentication.ui.DefaultLoginPageGeneratingFilter,
它来渲染默认的登录页面。既然我们选择了覆盖默认的URL,我们自己负责生成登录页面。
login-processing-url属性默认为/ j_spring_security_check,它指定登录表单(其中应包括用户名和密码)应提交时,使用的HTTP POST的URL。
当spring security处理此请求时,它会尝试对用户进行认证.
username-parameter和password-parameter参数属性默认为j_username和j_password,分别指定处理登录时,Spring Security将用来认证用户的HTTP参数。
如果用户名和密码提交到登录处理页面是无效的,authentication-failure-url属性指定Spring Security会重定向的URL
2.新建src/main/webapp/WEB-INF/views/login.jsp
<?xml version="1.0" encoding="ISO-8859-1" ?>
<%@ page language="java" contentType="text/html; charset=ISO-8859-1" pageEncoding="ISO-8859-1"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<c:set var="pageTitle" value="Please Login" scope="request"/>
<jsp:include page="./includes/header.jsp"/>
<c:url value="/login" var="loginUrl"/>
<form action="${loginUrl}" method="post">
<c:if test="${param.error != null}">
<div class="alert alert-error">
Failed to login.
<c:if test="${SPRING_SECURITY_LAST_EXCEPTION != null}">
Reason: <c:out value="${SPRING_SECURITY_LAST_EXCEPTION.
message}" />
</c:if>
</div>
</c:if>
<c:if test="${param.logout != null}">
<div class="alert alert-success">
You have been logged out.
</div>
</c:if>
<label for="username">Username</label>
<input type="text" id="username" name="username"/>
<label for="password">Password</label>
<input type="password" id="password" name="password"/>
<div class="form-actions">
<input id="submit" class="btn" name="submit" type="submit"
value="Login"/>
</div>
</form>
<jsp:include page="./includes/footer.jsp"/>
表单的action要匹配上面的login-processing-url,并且请求方式是post.session属性SPRING_SECURITY_LAST_EXCEPTION包含了最新o.s.s.core.AuthenticationException异常.
用来显示失败登录原因.input names匹配上面的username-parameter和password-parameter
3.让spring mvc识别新的url请求,在src/main/java/com/packtpub/springsecurity/web/config/WebMvcConfig.
java添加如下代码:
public void addViewControllers(ViewControllerRegistry registry){
registry.addViewController("/login/form").setViewName("login");
}
二.不急着测试,连登出也做了.
1.在security.xml继续配置http元素,添加
<logout logout-url="/logout"
logout-success-url="/login/form?logout"/>
logout-url指定登出的处理链接,默认是/j_spring_security_logout.实际上会被o.s.s.web.authentication.logout.LogoutFilter处理.
logout-success-url当然是成功登录后的跳转url
2.在src/main/webapp/WEB-INF/views/includes/header.jsp加上
<c:url var="logoutUrl" value="/logout"/>
<li>
<a href="${logoutUrl}">Logout</a>
</li>
在src/main/webapp/WEB-INF/views/login.jsp加上
<c:if test="${param.logout != null}">
<div class="alert alert-success">
You have been logged out.
</div>
</c:if>
3.重启jetty,会发现输入的登录url好像处理,起初我也怀疑是不是jetty坏了,实际上是被<intercept-url pattern="/**" access="ROLE_USER"/>它拦了,
登录页也无情,一样被拦,所以我们要排除登录和登出的页面被这配置拦截.在 <intercept-url pattern="/**" access="ROLE_USER"/>前面加上(为什么是前面就不必问了),
<intercept-url pattern="/" access="ROLE_ANONYMOUS,ROLE_USER"/>
<intercept-url pattern="/login/*"
access="ROLE_ANONYMOUS,ROLE_USER"/>
<intercept-url pattern="/logout"
access="ROLE_ANONYMOUS,ROLE_USER"/>
<intercept-url pattern="/events/" access="ROLE_ADMIN"/>
顺便在这个http元素之前再配置一个http,security设为none意味着这样的请求不会做权限处理.直接忽略让过.
<http pattern="/resources/**" security="none"/>
? 匹配单个字符
* 匹配0个或多个字符, 排除 /.
** 在一个路径匹配一个或多个目录.
4.重启jetty,发现可以正常登录了.
三.基于表达式的授权.使用了use-expressions设为true后,access配置就只能使用表达式语法了.permitAll还是一样能使用的.
例如像下面:
<http auto-config="true" use-expressions="true">
<intercept-url pattern="/" access="permitAll"/>
<intercept-url pattern="/login/*" access="permitAll"/>
<intercept-url pattern="/logout" access="permitAll"/>
<intercept-url pattern="/events/" access="hasRole('ROLE_ADMIN')"/>
<intercept-url pattern="/**" access="hasRole('ROLE_USER')"/>
<form-login ../>
...
</http>
可以重启jetty测试.
四.有条件地显示认证信息(指的是在jsp页面使用sec标签)
1.加入新依赖
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-taglibs</artifactId>
<version>3.1.0.RELEASE</version>
</dependency>
2.jsp引入标签就可以使用了
<%@ taglib prefix="sec" uri="http://www.springframework.org/security/tags" %>
<sec:authorize access="authenticated" var="authenticated"/>
<c:choose>
<c:when test="${authenticated}">
<li id="greeting">
<div>
Welcome
<sec:authentication property="name" />
</div>
</li>
<c:url var="logoutUrl" value="/logout"/>
<li>
<a id="navLogoutLink" href="${logoutUrl}">Logout</a>
</li>
</c:when>
<c:otherwise>
<c:url var="loginUrl" value="/login/form"/>
<li>
<a id="navLoginLink" href="${loginUrl}">Login</a>
</li>
</c:otherwise>
</c:choose>
可再次重启jetty测试了
五.登录后再想做些事情...即定义登录后的行为.
通过form-login元素的default-target-url属性,再在controller定义一个处理方法就OK了