Spring学习记录(Spring Securit)
来源:互联网 发布:linux 编辑文本命令 编辑:程序博客网 时间:2024/04/30 01:34
从URL访问级别、方法调用级别、页面视图显示级别和领域对象级别上用Spring Security加强Web应用安全。
一、加强URL访问安全
假定开发一个网上留言板应用,用户可以查看留言、记录留言、删除留言以及查询某一条留言,通过这个应用来理解SS的基本操作。
package com.zk.ss.pojo;/** * 留言板类 * */public class Message {private long id;private String author;//留言人姓名private String title;//留言标题private String body;//留言内容
接下来建一个服务接口,包含留言板的操作:
public interface MessageBoardService {List<Message> listMessage();//展示留言列表void postMessage(Message message);//张贴留言void deleteMessage(Message message);//删除留言Message findMessageById(Long messageId);//查询留言}
创建对应实现类:
public class MessageBoardServiceImpl implements MessageBoardService {//以张贴时间为键的留言列表集合private Map<Long, Message> messages = new LinkedHashMap<Long, Message>();public List<Message> listMessage() {return new ArrayList<Message>(messages.values());}//上传留言需线程安全public synchronized void postMessage(Message message) {message.setId(System.currentTimeMillis());messages.put(message.getId(), message);}//删除留言需线程安全public synchronized void deleteMessage(Message message) {messages.remove(message.getId());}public Message findMessageById(Long messageId) {return messages.get(messageId);}}
web.xml配置文件设置:
<!-- 不采用默认配置applicationContext.xml需要指定路径文件 --><context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/board-service.xml</param-value></context-param> <listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class> </listener><servlet><servlet-name>board</servlet-name><servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class></servlet><servlet-mapping><servlet-name>board</servlet-name><url-pattern>/</url-pattern></servlet-mapping>
Spring配置文件相关设置,此处分离成三个不同的文件:board-service.xml、board-servlet.xml、boardsecurity.xml,配置如下(需用到springmvc相关知识):
board-servlet.xml:
<context:component-scan base-package="com.zk.ss" /><bean class="org.springframework.web.servlet.view.InternalResourceViewResolver"><property name="prefix" value="/WEB-INF/jsp"></property><property name="suffix" value=".jsp"></property></bean>
board-service.xml:
<bean id="messageBoardService" class="com.zk.ss.service.MessageBoardServiceImpl"></bean>
创建控制器和页面视图:
@Controller@RequestMapping(value="/messageList*")public class MessageListController {@Autowiredprivate MessageBoardService messageBoardService;@RequestMapping(method = RequestMethod.GET)public String generateList(Model model){//生成一个不可变的list集合List<Message> messages = java.util.Collections.emptyList();messages = messageBoardService.listMessage();model.addAttribute("messages", messages);return "messageList";}}
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><!DOCTYPE><html> <head> <title>Message List</title> </head> <body> <c:forEach items="${messages }" var="message"> <table> <tr><td>Author</td><td>${message.author }</td></tr> <tr><td>Title</td><td>${message.title }</td></tr> <tr><td>Body</td><td>${message.body }</td></tr> <tr><td colspan="2"><a href="messageDelete?messageId=${message.id }">Delete</a></td></tr> </table> <hr/> </c:forEach> <a href="messagePost.htm">Post</a> </body></html>
此外,用户可以再留言板上张贴留言,因此需要创建对应的表单控制器:
@Controller@RequestMapping("/messagePost")public class MessagePostController {@Autowiredprivate MessageBoardService messageBoardService;@RequestMapping(method = RequestMethod.GET)public String setupForm(Model model){Message message = new Message();model.addAttribute("message", message);return "messagePost";}@RequestMapping(method = RequestMethod.POST)public String onSubmit(@ModelAttribute("message")Message message,BindingResult result){if(result.hasErrors()){return "messagePost";}else{messageBoardService.postMessage(message);return "redirect:messageList";}}}
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %><!DOCTYPE><html> <head> <title>Message Post</title> </head> <body><form:form method="POST" modelAttribute="message"><table><tr><td>Title</td><td><form:input path="title" /></td></tr><tr><td>Body</td><td><form:textarea path="body" /></td></tr><tr><td colspan="2"><input type="submit"" value="POST" /></td></tr></table></form:form> </body></html>
最后用户还可以单击留言表中的删除按钮删除张贴的留言,创建如下控制器:
@Controller@RequestMapping(value="/messageDelete*")public class MessageDeleteController {@Autowiredprivate MessageBoardService messageBoardService;@RequestMapping(method = RequestMethod.GET)public String messageDelete(@RequestParam(required=true,value="messageId")Long messageId,Model model){Message message = messageBoardService.findMessageById(messageId);messageBoardService.deleteMessage(message);model.addAttribute("messages", messageBoardService.listMessage());return "redirect:messageList";}}
如果工程名为Board,可以在Web容器(如Tomcat)中打开列表页面:http://localhost:8080/Board/messageList.htm
请求流程步骤:1、DispatcherServlet拦截所有的URL请求;2、DispatcherServlet询问BeanNameUrlHandlerMapping,根据messageList找到对应的Controller;3、DispatcherServlet分发给MessageListController来处理这个请求;4、MessageListController返回一个逻辑视图名"messageList";5、DispatcherServlet询问它的视图解析器(InternalResourceViewResolver)查找名为messageList的视图,InternalResourceViewResolver返回/WEB-INF/jsp/messageList.jsp路径;6、DispatcherServlet将请求导向对应页面
加入security,在web.xml中增加过滤器:
<context-param><param-name>contextConfigLocation</param-name><param-value>/WEB-INF/board-service.xml/WEB-INF/board-service.xml</param-value></context-param> <!-- 配置DelegatingFilterProxy实例,将HTTP请求过滤委派给Spring Security中定义的过滤器 --> <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>
boardsecurity.xml:
<?xml version='1.0' encoding='UTF-8'?><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.xsdhttp://www.springframework.org/schema/securityhttp://www.springframework.org/schema/security/spring-security-3.0.xsd'><!-- 对特定的url进行拦截,规定访问需要的权限 --><http auto-config="true"><intercept-url pattern="/messageList*" access="ROLE_USER,ROLE_ANONYMOUS"/><intercept-url pattern="/messagePost*" access="ROLE_USER"/><intercept-url pattern="/messageDelete*" access="ROLE_ADMIN"/></http><!-- 配置验证服务,Security支持多种验证方法,包括数据库或LDAP存储库的验证对于简单的安全需求,还可以直接在<user-service>中定义 --><authentication-manager><authentication-provider><user-service><user name="admin" password="admin" authorities="ROLE_ADMIN,ROLE_USER"/><user name="user1" password="1234" authorities="ROLE_USER"/></user-service></authentication-provider></authentication-manager></beans:beans>
此时,我们可以直接访问messageList.htm,因为它开放给匿名用户,而如果直接访问messagePost.htm,则会被重新定向到Spring Security生成的默认登录页面。
二、登录到Wen应用
现在我们取消spring自动配置的http服务属性auto-config="true",手动配置登录页,匿名用户,remember me等
首先创建登录页login.jsp:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%><%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %><!DOCTYPE><html> <head> <title>Login</title><!-- 基于表单的登录需在xml文档中配置(我们取消了auto-config="true"的http自动配置服务)<http>...<form-login /></http>该登录页可代替spring security默认的登录页spring_security_login配置在web-inf根目录下,可让用户直接访问 --> </head> <!-- 此处的表单操作url和字段名称都是固定的 --> <body><c:if test="${not empty param.error}"><font color="red">Login error.<br>Reason:${sessionScope["SPRING_SECURITY_LAST_EXCEPTION"].message }</font></c:if><form method="POST" action="<c:url value="/j_spring_security_check" />" ><table><tr><td align="right"">Username</td><td><input type="text" name="j_username" /></td></tr><tr><td align="right">Password</td><td><input type="password" name="j_password" /></td></tr><tr><td align="right">Remember me</td><td><input type="checkbox" name="_spring_security_remember_me" /></td></tr><tr><td colspan="2" align="right"><input type="submit" value="Login" /><input type="reset" value="Reset" ></td></tr></table></form> </body></html>
修改boardsecurity.xml配置文件:
<!-- 对特定的url进行拦截,规定访问需要的权限 --><http><!-- 删除auto-config="true" 禁用http自动配置 --><intercept-url pattern="/messageList*" access="ROLE_USER,ROLE_GUEST"/><intercept-url pattern="/messagePost*" access="ROLE_USER"/><intercept-url pattern="/messageDelete*" access="ROLE_ADMIN"/><!-- 配置自定义的表单登录页面 1、如果用户请求安全url时显示登录界面,登录成功后会被重新定位到目标url,但是用户直接访问登录界面,登录成功后会重新定向到上下文跟路径(http://localhost:8080/board/),默认的欢迎页面default-target-url可以设置用户直接访问登陆界面登录成功后显示的页面2、在默认的登录页面下,登录失败后spring会带着错误的信息显示在这个登录页面,如果自定义登录页面就必须配置authentication-failure-url,指定错误时重定向的url,例如:可以使用error请求参数再次重定向到自定义的登录页面--><form-login login-page="/login.jsp" default-target-url="/messageList"authentication-failure-url="/login.jsp?error=true"/><!-- 注销服务:默认情况下,注销服务映射到url /j_spring_security_logout --><logout logout-success-url="/login.jsp"/><!-- 匿名登录:用户可以自定义匿名用户的用户名和权限 --> <anonymous username="guest" granted-authority="ROLE_GUEST" /> <!-- remember me支持 --> <remember-me/></http>
在messageList.jsp中增加按钮测试:
<body> <c:forEach items="${messages }" var="message"> <table> <tr><td>Author</td><td>${message.author }</td></tr> <tr><td>Title</td><td>${message.title }</td></tr> <tr><td>Body</td><td>${message.body }</td></tr> <tr><td colspan="2"><a href="messageDelete?messageId=${message.id }">Delete</a></td></tr> </table> <hr/> </c:forEach> <a href="messagePost.html">Post</a> <a href="<c:url value="/login.jsp" />">Login</a> <a href="<c:url value="/j_spring_security_logout" />">Logout</a> </body>
- Spring学习记录(Spring Securit)
- spring securit(五)
- Spring学习记录
- Spring 学习记录 5
- Spring 学习记录 6
- Spring学习记录-AOP
- Spring事务学习记录
- spring学习记录(一)
- Spring框架学习记录
- spring security 学习记录
- spring 学习 错误记录
- Spring学习记录
- Spring学习记录
- Spring AOP学习记录
- maven spring学习记录
- Spring boot学习记录
- spring aop学习记录
- 学习Spring Framework的记录(1)
- Android Message和obtainMessage的区别
- 从反转字符串中看指针魅力
- Javascript中最常用的55个经典技巧
- 数据结构——队列及循环队列
- unity学习之异常,修饰符
- Spring学习记录(Spring Securit)
- C语言中的typedef问题
- 文明的历程
- C程序
- 杭电OJ(HDOJ)4920题:Matrix multiplication(线性代数,矩阵相乘)
- linux命令
- VB字符串拼接
- Android平台使用log4j
- 【BZOJ】【P2802】【POI2012】【Warehouse Store】【题解】【贪心】