Spring Security学习二 - 自定义Login方法
来源:互联网 发布:faceu是什么软件 编辑:程序博客网 时间:2024/04/30 22:15
Author: Kagula
Date: 2016-9-19
环境
[1]Spring 3.1.2
[2]Tomcat 7.x
概要
在《Spring Security学习一》的基础上完善自定义Login界面,并增加了Login方法的自定义。
这里仅列出源码。
测试内容
[1]能否把密码明文转成密文,MD5加密。pass.
[2]能否同Spring MVC兼容。pass.
[3]自定义login方法。pass.
[4]个性化提示用户没有权限。pass.
[5]排除对jpg等图片的权限检查。pass.
[6]增加一组URL的权限检查。pass.
[7]自定义404错误。pass.
正文
第一部份配置文件
文档结构如图
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>com.nuoke</groupId> <artifactId>testSpringSecurity2</artifactId> <packaging>war</packaging> <version>0.0.1-SNAPSHOT</version> <name>testSpringSecurity2 Maven Webapp</name> <url>http://maven.apache.org</url> <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding><spring.version>3.1.2.RELEASE</spring.version> </properties> <dependencies> <dependency><groupId>org.springframework</groupId><artifactId>spring-core</artifactId><version>${spring.version}</version><!-- <exclusions> <exclusion> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> </exclusion> </exclusions> --></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-beans</artifactId><version>${spring.version}</version></dependency><dependency><groupId>org.springframework</groupId><artifactId>spring-webmvc</artifactId><version>${spring.version}</version></dependency><dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-core</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-web</artifactId> <version>${spring.version}</version></dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-config</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-taglibs</artifactId> <version>${spring.version}</version> </dependency> <dependency> <groupId>jstl</groupId> <artifactId>jstl</artifactId> <version>1.2</version> </dependency> </dependencies> <build> <finalName>testSpringSecurity2</finalName> <plugins> <!-- 为了解决“Dynamic Web Module 3.0 requires Java 1.6 or newer.”错误需要下面的plugin --> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <version>3.0</version> <configuration> <source>1.7</source> <target>1.7</target> </configuration> </plugin> </plugins> </build></project>
web.xml
<?xml version="1.0" encoding="UTF-8"?><web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://java.sun.com/xml/ns/javaee" xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" id="schedule-console" version="3.0"> <display-name>Archetype Created Web Application</display-name> <!-- 配置字符集过滤器 --> <!-- 必须配置在所有过滤器的前面 --> <filter> <filter-name>encodingFilter</filter-name> <filter-class>org.springframework.web.filter.CharacterEncodingFilter</filter-class> <init-param> <param-name>encoding</param-name> <param-value>UTF-8</param-value> </init-param> </filter> <!-- 配置项目的编码mapping --> <filter-mapping> <filter-name>encodingFilter</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- 如果同一个bean被定义两次,后面一个优先 --> <context-param> <param-name>contextConfigLocation</param-name> <param-value>/WEB-INF/spring-servlet.xml,/WEB-INF/spring-security.xml</param-value> </context-param> <!-- 启动spring容器用,容器用于管理Bean --> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener> <!-- Spring Security会话控制 --> <listener> <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class> </listener> <!-- Spring security Filter --> <filter> <filter-name>springSecurityFilterChain</filter-name> <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class> </filter> <filter-mapping> <filter-name>springSecurityFilterChain</filter-name> <url-pattern>/*</url-pattern> </filter-mapping> <!-- DispatcherServlet 针对MVC上下文加载,即拦截请求,分发请求给Controller --> <!-- 《ContextLoaderListener初始化的前后文和DispatcherServlet初始化的上下文关系》 http://www.educity.cn/wenda/356953.html --> <servlet> <servlet-name>spring</servlet-name> <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class> <load-on-startup>1</load-on-startup> </servlet> <!-- url-pattern配置为/,不带文件后缀,会造成其它静态文件(js,css等)不能访问。如配为*.do,则不影响静态文件的访问 --> <servlet-mapping> <servlet-name>spring</servlet-name> <url-pattern>*.do</url-pattern> </servlet-mapping> <welcome-file-list> <welcome-file>index.jsp</welcome-file> </welcome-file-list> <error-page> <error-code>404</error-code> <location>/My404.jsp</location> </error-page> <error-page> <exception-type>java.lang.Exception</exception-type> <location>/MyEception.jsp</location> </error-page> </web-app>
spring-servlet.xml
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:mvc="http://www.springframework.org/schema/mvc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.1.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.1.xsd http://www.springframework.org/schema/mvc http://www.springframework.org/schema/mvc/spring-mvc.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.1.xsd"> <!-- Scan Controller Range --> <context:component-scan base-package="com.nuoke.controller" /><!-- HandlerMapping --> <bean class="org.springframework.web.servlet.handler.BeanNameUrlHandlerMapping" /> <!-- HandlerAdapter --> <bean class="org.springframework.web.servlet.mvc.SimpleControllerHandlerAdapter" /> <!-- enable spring mvc annotation driven--><mvc:annotation-driven/> <bean id="jspViewResolver"class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/view/" /><property name="suffix" value=".jsp" /></bean><!--定义异常处理页面--><!-- 具体哪个页面在web.xml中设置 --> <bean id="exceptionResolver" class="org.springframework.web.servlet.handler.SimpleMappingExceptionResolver"> <property name="exceptionMappings"> <props> <prop key="java.sql.SQLException">outException</prop> <prop key="java.io.IOException">outException</prop> </props> </property> </bean></beans>
spring-security.xml
<?xml version="1.0" encoding="UTF-8"?> <b:beans xmlns="http://www.springframework.org/schema/security" xmlns:b="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.1.xsd"> <!--此页面不过滤 --> <!--仅自定义登录页面的示例 --> <http pattern="/main/login.do" security="none" /> <!--自定义登录方法的示例 --> <http pattern="/main/customLogin.do" security="none" /> <!-- 此目录下不过滤 --> <!-- example http://localhost:8080/testSpringSecurity2/download/c.png --> <http pattern="/download/**" security="none" /> <!-- 从来没见过auto jump into accessDenied.jsp --> <http access-denied-page="/accessDenied.jsp"> <!-- login-page:默认指定的登录页面. authentication-failure-url:出错后跳转页面. default-target-url:成功登陆后跳转页面 默认登录保护url --> <!-- 示例 一:自定义登录页面 --> <!-- <form-login login-page="/main/login.do" default-target-url="/main/welcome.do" authentication-failure-url="/main/login.do?error" login-processing-url="/j_spring_security_check" username-parameter="username" password-parameter="password" /> --> <!-- 示例二:自定义登录方法 --> <!-- 示例二是在示例一Controller的基础上增加一个handler --> <!-- view目录下增加了customLogin.jsp、customLoginResponse.jsp两个jsp,组成。 --> <form-login login-page="/main/customLogin.do" default-target-url="/main/welcome.do"/> <!-- logout-success-url:成功注销后跳转到的页面; --> <!-- 示例一和示例二的代码可以同时运行 --> <logout logout-url="/j_spring_security_logout" logout-success-url="/main/login.do" invalidate-session="true" /> <!--访问资源必须有ROLE_ADMIN的权限 --> <intercept-url pattern="/main/welcome.do" access="ROLE_ADMIN" /> <!--访问/**资源的用户必须具有ROLE_USER的权限 --> <!-- <intercept-url pattern="/**" access="ROLE_USER" /> --> <!-- 奇怪下面的intercept-url设定对chrome不起作用,但是对IE和Eclipse中的Web Browser起作用。 --> <!-- 发现,是因为有一次重启session还是有效造成的 --> <!-- pattern="/*.do"的设定是不起作用的 --> <!-- pattern="/main/*.do"的设定有效的 --> <!-- <intercept-url pattern="/main/**" access="ROLE_USER,ROLE_ADMIN" /> --> <session-management invalid-session-url="/sessionexpired.jsp"> <!-- 必须要有invalid-session-url属性,否则不会踢掉原来的登录 --> <!-- 被踢掉的用户再发出请求会转到/sessionexpired.jsp页面 --> <concurrency-control max-sessions="1" error-if-maximum-exceeded="false"/> <!-- error-if-maximum-exceeded属性为false的话,踢掉原来的登录, max-sessions默认为1 --> <!-- expired-url="/kickout.jsp" 不设置的话会提示This session has been expired (possibly due to multiple concurrent logins being attempted as the same user). --> <!-- 然后再刷新的话,转到/sessionexpired.jsp --> <!-- expired-url="/kickout.jsp" 设置的话会转到/sessionexpired.jsp--> <!-- error-if-maximum-exceeded属性为true的话,如果帐号已经登录,在其它地方这个帐号就登录不了了 --> </session-management> <custom-filter ref="myFilter" before="FILTER_SECURITY_INTERCEPTOR" /> </http> <!--一个自定义的filter,必须包含 authenticationManager,accessDecisionManager,securityMetadataSource三个属性, 我们的所有控制将在这三个类中实现,解释详见具体配置 --> <b:bean id="myFilter" class="com.nuoke.MyFilterSecurityInterceptor"> <b:property name="authenticationManager" ref="authenticationManager" /> <b:property name="accessDecisionManager" ref="myAccessDecisionManagerBean" /> <b:property name="securityMetadataSource" ref="securityMetadataSource" /> </b:bean> <!--验证配置,认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 --> <authentication-manager alias="authenticationManager"> <authentication-provider user-service-ref="myUserDetailService"> <!--如果用户的密码采用加密的话 --> <password-encoder hash="md5"/> </authentication-provider> </authentication-manager> <!--在这个类中,你就可以从数据库中读入用户的密码,角色信息,是否锁定,账号是否过期等 --> <b:bean id="myUserDetailService" class="com.nuoke.MyUserDetailService" /> <!--访问决策器,决定某个用户具有的角色,是否有足够的权限去访问某个资源 --> <b:bean id="myAccessDecisionManagerBean" class="com.nuoke.MyAccessDecisionManager"> </b:bean> <!--资源数据定义,将所有的资源和权限对应关系建立起来,即定义某一资源可以被哪些角色访问 --> <b:bean id="securityMetadataSource" class="com.nuoke.MyInvocationSecurityMetadataSource" /> </b:beans>
第二部份java源文件
共有7个class文件,这里只列出《学习一》内容不同或没有的java源文件
MyUserDetailService.java
package com.nuoke;import java.util.ArrayList;import java.util.Collection;import org.springframework.dao.DataAccessException;import org.springframework.security.core.GrantedAuthority;import org.springframework.security.core.authority.SimpleGrantedAuthority;import org.springframework.security.core.userdetails.User;import org.springframework.security.core.userdetails.UserDetails;import org.springframework.security.core.userdetails.UserDetailsService;import org.springframework.security.core.userdetails.UsernameNotFoundException; public class MyUserDetailService implements UserDetailsService { //登陆验证时,通过username获取用户的所有权限信息, //并返回User放到spring的全局缓存SecurityContextHolder中,以供授权器使用 public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException, DataAccessException { Collection<GrantedAuthority> auths=new ArrayList<GrantedAuthority>(); SimpleGrantedAuthority auth2 = new SimpleGrantedAuthority("ROLE_ADMIN"); SimpleGrantedAuthority auth1 = new SimpleGrantedAuthority("ROLE_USER"); if(username.equals("admin")){ auths=new ArrayList<GrantedAuthority>(); auths.add(auth1); auths.add(auth2); } //第二个参数是密码。是123的md5码。 User user = new User(username, "202cb962ac59075b964b07152d234b70", true, true, true, true, auths); //以后还可以new a class derived from User class,为user存放更多有关这个user的信息。 //参考下文User定义,可以存放用户的更多属性。 //http://blog.csdn.net/ydj7501603/article/details/9049663 return user; } }
MyController.java
package com.nuoke.controller;import javax.servlet.http.HttpServletRequest;import javax.servlet.http.HttpSession;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.security.authentication.AuthenticationManager;import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;import org.springframework.security.core.Authentication;import org.springframework.security.core.AuthenticationException;import org.springframework.security.core.context.SecurityContextHolder;import org.springframework.security.core.userdetails.User;import org.springframework.stereotype.Controller;import org.springframework.web.bind.annotation.RequestMapping;import org.springframework.web.bind.annotation.RequestParam;import org.springframework.web.bind.annotation.ResponseBody;import org.springframework.web.servlet.ModelAndView;@Controller@RequestMapping(value = "/main")public class MyController {@RequestMapping(value = "/admin.do")public ModelAndView adminPage() {ModelAndView model = new ModelAndView();model.addObject("title", "Spring Security Hello World");model.addObject("message", "这是一个安全被保护的页面!");//在MyInvocationSecurityMetadataSource类中指定了保护。model.setViewName("admin");return model;}@RequestMapping(value = "/welcome.do")public ModelAndView WelcomeAction() {ModelAndView model = new ModelAndView();model.addObject("title", "Spring Security Hello World");model.addObject("message", "这是一个欢迎页面!");model.setViewName("welcome");return model;}/* * 仅自定义login页面 * 测试url: * http://localhost:8080/testSpringSecurity2/main/login.do */@RequestMapping(value = "/login.do")public ModelAndView LoginAction(@RequestParam(value = "error", required = false) String error,@RequestParam(value = "logout", required = false) String logout) {ModelAndView model = new ModelAndView();if (error != null) {model.addObject("error", "用户名或密码不正确!");}if (logout != null) {model.addObject("msg", "您已成功注销系统.");}model.setViewName("login");return model;}//自定义Login方法示例/* * 测试Url: * http://localhost:8080/testSpringSecurity2/main/customLogin.do * * 补充参考资料: * 《在spring security手动 自定义 用户认证 SecurityContextHolder》 * https://my.oschina.net/lemonzone2010/blog/268452#OSC_h2_1 * 《》 * http://www.programcreek.com/java-api-examples/index.php?api=org.springframework.security.core.context.SecurityContext */@Autowired private AuthenticationManager authenticationManager;@RequestMapping(value="/customLogin.do")public ModelAndView customLoginAction(@RequestParam(defaultValue="") String username, @RequestParam(defaultValue="") String password, HttpServletRequest request){//username = username.trim();//返回登录页面 ModelAndView model = new ModelAndView(); model.setViewName("customLogin");if(username==null||username.isEmpty()||password==null||password.isEmpty()){return model;}//向AJAX请求返回消息提醒(json字符串)model.setViewName("customLoginResponse");UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password); //try {Authentication authentication = authenticationManager.authenticate(authRequest); SecurityContextHolder.getContext().setAuthentication(authentication); HttpSession session = request.getSession(); session.setAttribute("SPRING_SECURITY_CONTEXT", SecurityContextHolder.getContext()); // 这个非常重要,否则验证后将无法登陆 model.addObject("message","登录用户:"+authentication.getName()); model.addObject("ok",1);//这样view/customLogin.jsp得到成功标记后可以做url跳转。 } catch (AuthenticationException ex) { model.addObject("message","用户名或密码错误"); model.addObject("ok",0);//为了view/customLogin.jsp得到失败标记后可以提醒用户重新输入用户名、密码。 }//end catch return model;}//end handler}//end class
第三部份jsp源文件
参考图一共有十个jsp文件,这里只列出比较重要的几个jsp。
MyException.jsp
<%@ page contentType="text/html;charset=UTF-8" language="java" %><html><head> <title>异常处理页面</title></head><body><% Exception ex = (Exception) request.getAttribute("Exception");%><H2>Exception:<%=ex.getMessage()%></H2></body></html>
login.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%><!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>示例一:自定义登录界面</title> <style> .error { padding: 15px; margin-bottom: 20px; border: 1px solid transparent; border-radius: 4px; color: #a94442; background-color: #f2dede; border-color: #ebccd1; } .msg { padding: 15px; margin-bottom: 20px; border: 1px solid transparent; border-radius: 4px; color: #31708f; background-color: #d9edf7; border-color: #bce8f1; } #login-box { width: 300px; padding: 20px; margin: 100px auto; background: #fff; -webkit-border-radius: 2px; -moz-border-radius: 2px; border: 1px solid #000; } </style></head><body onload='document.loginForm.username.focus();'> <div id="login-box"> <h2>请输入您的用户名与密码</h2> <c:if test="${not empty error}"> <div class="error">${error}</div> </c:if> <c:if test="${not empty msg}"> <div class="msg">${msg}</div> </c:if> <form name='loginForm' action="<c:url value='/j_spring_security_check' />" method='POST'> <table> <tr> <td>用户:</td> <td><input type='text' name='username' value=''></td> </tr> <tr> <td>密码:</td> <td><input type='password' name='password' /></td> </tr> <tr> <td colspan='2'><input name="submit" type="submit" value="登录" /></td> </tr> </table> <!-- 猜测_csrf是给不支持Cookie的Web Browser准备的。 --> <!-- <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> --> </form> </div></body></html>
welcome.jsp
<%@ page language="java" import="java.util.*,java.text.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%@page session="false"%><html><body> <h1>标题 : ${title}</h1> <h1>消息 : ${message}</h1> <br> <% Date date = new Date(); SimpleDateFormat t = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); String time = t.format(date);%><br/>当前时间:<%= time %> </body></html>
admin.jsp
<%@page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%@page session="true"%><html><body> <h1>标题 : ${title}</h1> <h1>消息 : ${message}</h1> <c:url value="/j_spring_security_logout" var="logoutUrl" /> <form action="${logoutUrl}" method="post" id="logoutForm"> <!-- csrf for log out--> <!-- 猜测_csrf是给不支持Cookie的Web Browser准备的。 --> <!-- <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" /> --> </form> <script> function formSubmit() { document.getElementById("logoutForm").submit(); } </script> <c:if test="${pageContext.request.userPrincipal.name != null}"> <h2> 欢迎 : ${pageContext.request.userPrincipal.name} 登录本系统 | <a href="javascript:formSubmit()"> 注销</a> </h2> </c:if></body></html>
customLogin.jsp
<%@ page language="java" contentType="text/html; charset=UTF-8"pageEncoding="UTF-8"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><html><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"><title>自定义登录控制</title><link href="../common/bootstrap/css/bootstrap.min.css" rel="stylesheet"><link href="../common/bootstrap/css/bootstrap-theme.min.css" rel="stylesheet"><script type="text/javascript"src="../common/bootstrap/js/bootstrap.min.js"></script><script type="text/javascript" src="../common/jquery/jquery-2.1.1.min.js"></script><body><div class="container"><div id="container_demo"><div id="wrapper"><div id="login" class="animate form"><h1>示例二 自定义login方法</h1><form id='loginForm' method="POST"><p><label for="" class="uname" data-icon="u"> 用户名 </label> <input id="username" name="username" required="required" type="text" placeholder="myusername or mymail@mail.com"></p><p><label for="" class="youpasswd" data-icon="p"> 密码 </label><input id="password" name="password" required="required" type="password" placeholder="eg. X8df!90EO"></p><p class="login button"><input type="submit" id="submitId" value="登录"></p></form></div></div></div></div></body><script type="text/javascript"> $(function(){ /////////////////登录提交//////////////////////////// $("#loginForm").submit(function() { var username=$("#username").val(); var password=$("#password").val(); var data={username:username,password:password}; var url="/testSpringSecurity2/main/customLogin.do"; $.ajax({ type: "POST", url: url, data: data, // contentType: "application/json", dataType: "json", success:function (result) { if(result.ok){ location.href="/testSpringSecurity2/main/admin.do"; } else { $(".error").remove(); $("#loginForm").prepend("<div class='error'><font color='red'>"+result.msg+"</font></div>"); } }, error:function(XMLHttpRequest, textStatus, errorThrown){ alert('读取超时,请检查网络连接...'); } }); return false; }); }); </script></html>
customLoginResponse.jsp
<%@ page language="java" import="java.util.*,java.text.*" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%><%@page session="false"%>{"ok":${ok},"msg":"${message}"}
遗留问题
登录的时候,如何知道帐户已经在其它地方登录?
参考资料
[1]《Spring Security》
http://docs.spring.io/spring-security/site/docs/3.1.x/reference/springsecurity.html
[2]《intercept-url配置》
参考这篇文章可以限定用户只能使用https协议访问服务
http://haohaoxuexi.iteye.com/blog/2161056
[3]《Spring Security 3.1.2 + Spring Framework 3.1.2+使用Annotation实战指南》
http://www.itpub.net/thread-1719846-1-1.html
[4]《Spring Security 3.1 自定义实例之登陆》
使用AJAX来验证登录
使用了spring自带的login方法来验证登录
http://www.cnblogs.com/ilife/archive/2013/02/28/2936067.html
[5]《Spring Security 3.1.2.RELEASE API》
http://tool.oschina.net/uploads/apidocs/spring-security-3.1.2/apidocs/
[6]《spring security Controller用户角色的判断》
http://blog.csdn.net/softwarehe/article/details/7711302
[7]《How to manually log out a user with spring security?》
http://stackoverflow.com/questions/5727380/how-to-manually-log-out-a-user-with-spring-security
[8]《Spring and Angular JS: A Secure Single Page Application》
https://spring.io/blog/2015/01/12/spring-and-angular-js-a-secure-single-page-application
- Spring Security学习二 - 自定义Login方法
- Spring Security自定义Login
- Spring Security Form Login
- spring security 3 自定义(二)
- Spring Security笔记:自定义Login/Logout Filter、AuthenticationProvider、AuthenticationToken
- Spring Security笔记:自定义Login/Logout Filter、AuthenticationProvider、AuthenticationToken
- Spring Security笔记:自定义Login/Logout Filter、AuthenticationProvider、AuthenticationToken
- Spring Security笔记:自定义Login/Logout Filter、AuthenticationProvider、AuthenticationToken
- Spring Security笔记:自定义Login/Logout Filter、AuthenticationProvider、AuthenticationToken
- Spring Security学习笔记自定义登录页面(二)
- Spring Security学习总结二
- Spring Security学习总结二
- Spring Security学习总结二
- Spring Security学习总结二
- Spring security学习笔记二
- Spring Security学习总结二
- spring security起步二:自定义登录页
- spring security起步二:自定义登录页
- C# 简单接口及接口属性定义!!
- cocoapods 安装 常见问题及其解决方案汇总
- WIFI/蓝牙/NFC/传感器
- PhotoView图片的放大和缩小的用法
- 111111111111111111111111
- Spring Security学习二 - 自定义Login方法
- 简单工厂模式——2016手机也疯狂
- 二级C语言复习7
- 详细解释javascript的冒泡和捕获
- Fortran 上机实验
- 进程、线程区别
- solrCloud+tomcat+zookeeper配置----参考一
- SDK#屏幕兼容性模式
- Elasticsearch 2.4.0 maven jar包