SpringSecurity3.1入门教程(四)

一.前言

前面三篇介绍了security,磨刀不误砍柴工,现在就开始上代码吧。本文的项目demo地址可以在文章尾部看到。

二.DEMO

1.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="WebApp_ID" version="3.0">
	<listener>
	    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
	</listener>
	<context-param>
	    <param-name>contextConfigLocation</param-name>
	    <param-value>classpath:/resources/spring-security.xml</param-value>
	</context-param>
	    <!-- Spring 刷新Introspector防止内存泄露 -->
	<listener>
		<listener-class>
			org.springframework.web.util.IntrospectorCleanupListener
		</listener-class>
	</listener>
	
	<!-- 配置log4j,在这里配置可以动态的改变log4j里面的内容,从而不用重启服务器就可以让新样式生效 -->
	  <listener>
    <listener-class>  
            org.springframework.web.util.Log4jConfigListener   
        </listener-class>
  </listener>
  <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>classpath:/resources/log4j.properties</param-value>
  </context-param>
  <context-param>
    <param-name>log4jRefreshInterval</param-name>
    <param-value>6000</param-value>
  </context-param>
	
	<!--  session会话管理-->
  	<listener>
		<listener-class>
			org.springframework.security.web.session.HttpSessionEventPublisher 
		</listener-class>
	</listener>

	<!-- session超时定义,单位为分钟 -->
	<session-config>
		<session-timeout>1</session-timeout>
	</session-config>
	<!-- 编码过滤器 -->
	<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>
	<filter-mapping>
		<filter-name>encodingFilter</filter-name>
		<url-pattern>/*</url-pattern>
	</filter-mapping>
	<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>
</web-app>

2.spring-security.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.1.xsd
           http://www.springframework.org/schema/security
           http://www.springframework.org/schema/security/spring-security-3.1.xsd">
    <!-- 对登录页面不进行拦截,否则会进入死循环 -->
    <http pattern="/login.jsp" security="none"/> 
	<http auto-config="true"  access-decision-manager-ref="accessDecisionManager"><!-- access-decision-manager-ref涉及到角色继承 -->
        <form-login login-page="/login.jsp" default-target-url="/index.jsp" authentication-failure-url="/login.jsp?error=1" />
		<!-- 尝试访问没有权限的页面时跳转的页面 -->   
		<access-denied-handler error-page="/accessDeny.jsp"/> 
		<intercept-url pattern="/**" access="ROLE_USER"/>
		<!-- 注销成功跳转到登录页面 -->
		<logout logout-success-url="/login.jsp" logout-url="/j_spring_security_logout" invalidate-session="true" delete-cookies="JSESSIONID"/>
		<!-- 同步会话管理,设置允许同一个账户登录2次 ,一般都是设置1次-->
		<session-management invalid-session-url="/timeout.jsp" > <!-- invalid-session-url设置连接超时跳转页面 -->
		<!-- error-if-maximum-exceeded="true":超出最大连接数以后,false-后登陆的将先登录的挤出系统,true: 后面的用户禁止登陆 -->
        	<concurrency-control max-sessions="2" error-if-maximum-exceeded="true" />
   		</session-management>
   		<!-- 防止session攻击,在用户登录时销毁用户当前session,并生成新session,但不会复制任何原有属性 -->
   		<session-management session-fixation-protection="newSession"/>
</http>
   
	<!-- 验证配置 , 认证管理器,实现用户认证的入口,主要实现UserDetailsService接口即可 -->
	<authentication-manager>
		<authentication-provider user-service-ref="myUserDetailsService"> 
		<!-- <authentication-provider>
		   <user-service>
		    <user name="zhou" password="123" authorities="ROLE_ADMIN"/>
		    </user-service>
		 -->
		<!-- 使用用户名作为盐值 -->
		  
		<!-- 	<password-encoder hash="md5">
				<salt-source user-property="username" />
			</password-encoder> -->
		</authentication-provider>
	</authentication-manager>

	
		<!-- 启用角色继承功能,ROLE_ADMIN > ROLE_USER表示只要是允许ROLE_USER访问的资源,
		ROLE_ADMIN也都有权限进行访问,去掉START和END之间的代码一样是能正常运行的 ,
		但是因为在MyUserDetialsService类中authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
		我只分配了他管理员角色,所以会跳转到accessDeny.jsp。
	            去掉角色继承功能时记得除去<http  access-decision-manager-ref="accessDecisionManager">属性-->
	             <!-- START -->
	
	<beans:bean id="accessDecisionManager" class="org.springframework.security.access.vote.AffirmativeBased">
	<beans:property name="allowIfAllAbstainDecisions" value="false"/>
	<beans:property name="decisionVoters">
		<beans:list>
			<beans:ref bean="roleHierarchyVoter"/>
			<beans:ref bean="authenticatedVoter"/>
		</beans:list>
	</beans:property>
</beans:bean>

<beans:bean id="roleHierarchyVoter" class="org.springframework.security.access.vote.RoleHierarchyVoter">
    <beans:constructor-arg ref="roleHierarchy"/>
</beans:bean>

<beans:bean id="authenticatedVoter" class="org.springframework.security.access.vote.AuthenticatedVoter"/>

<beans:bean id="roleHierarchy" class="org.springframework.security.access.hierarchicalroles.RoleHierarchyImpl">
   <!--  <beans:property name="hierarchy" value="ROLE_ADMIN > ROLE_USER"/> -->
    <!-- 如果希望配置更多继承关系,可以使用换行进行分隔 -->
    <beans:property name="hierarchy">
        <beans:value>
            ROLE_ADMIN > ROLE_USER
            ROLE_MANAGER > ROLE_USER
        </beans:value>
    </beans:property>
    
</beans:bean>
	
	
	
   <!-- END -->	
	
	
	
	
	
	<beans:bean id="myUserDetailsService" class="com.zsj.MyUserDetialsService" />  
 	    
    <!-- 定义国际化,支持中文异常信息 -->
    <beans:bean id="messageSource"
   		 class="org.springframework.context.support.ReloadableResourceBundleMessageSource">
 		 <beans:property name="basename" 
 		 	value="classpath*:/messages_zh_CN"/>
	</beans:bean>
</beans:beans>

3.UserDetailsService

package com.zsj;

import java.io.IOException;
import java.io.Reader;
import java.security.Principal;
import java.util.ArrayList;
import java.util.Collection;
import org.apache.ibatis.io.Resources;
import org.apache.ibatis.session.SqlSession;
import org.apache.ibatis.session.SqlSessionFactory;
import org.apache.ibatis.session.SqlSessionFactoryBuilder;
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 MyUserDetialsService implements UserDetailsService {

	@Override
	public UserDetails loadUserByUsername(String name) throws UsernameNotFoundException {
		// TODO Auto-generated method stub
		UserDetails userDetails=null;
		UserInfo user=null;
		try {
			 user=(UserInfo) findByName(name);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		if(user==null){
			throw new UsernameNotFoundException("该用户并不存在");
		}else{
			Collection<GrantedAuthority> authorities = new ArrayList<>();
			//这里我就直接赋值ROLE_ADMIN了,真正项目是要从数据库获取角色
			authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
			userDetails=new User(user.getUserName(),user.getPassword()+"",authorities);
			System.out.println(userDetails);
		}
		return userDetails;
	}
//为简化项目,直接上恶心的原始mybatis吧,不和spring集成了,这里也可以换成你设计的查找用户的DAO。
 public UserInfo findByName(String name) throws IOException{
	String config="resources/mybatis-config.xml";
	Reader reader=Resources.getResourceAsReader(config);//Resources 类为从类路径中加载资源
	SqlSessionFactory sessionFactory = new SqlSessionFactoryBuilder().build(reader);
	SqlSession session = sessionFactory.openSession();
	 /**
     * 映射sql的标识字符串,
     * com.dao.DeptDao是deptMapper.xml文件中mapper标签的namespace属性的值,
     * findByDeptNum是select标签的id属性值,通过select标签的id属性值就可以找到要执行的SQL
     */
	String statement = "com.zsj.UserDao.findByUserName";//请注意这里是点分,不是正斜杠
	String param = "zhou";
	UserInfo user = session.selectOne(statement, param);//执行DeptDao中的findByDeptNum方法,方法参数为"D001"
	System.out.println(user.getPassword());
	return user;
}
}

4.login.jsp

<%@page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>登录</title>
</head>
<body>
<!--特别强调,请注意红色字体!!!!!!!!-->
<form action="<span style="color:#FF0000;">j_spring_security_check</span>" method="POST">
<table>
	<tr>
		<td>用户:</td>
		<td><input type='text' name=<span style="color:#FF0000;">'j_username</span>'></td>
	</tr>
	<tr>
		<td>密码:</td>
		<td><input type='password' name='<span style="color:#FF0000;">j_password</span>'></td>
	</tr>
	<tr>
                <td>记住我<input id="_spring_security_remember_me" name="_spring_security_remember_me" type="checkbox" value="true"/></td>
                <td><input name="reset" type="reset"></td>
		<td><input name="submit" type="submit"></td>
	</tr>
</table>
</form>
</body>
</html>

5.运作流程

(1).网址输入http://localhost:8080/TestSecurity

(2)由于security拦截器拦截作用,改请求会被拦截,由于没有登录认证,会被定向到登录页面

(3)登录页面输入账号密码,请求跳转到主页,该请求又被拦截,会拦截器会调用认证管理器,认证供应器来认证用户,认证成功则接着验证授权,认证和授权都通过才可以进入主页

6.结尾

如需项目DEMO的源码,请到下面地址下载:http://download.csdn.net/detail/u012557538/9373827

学习博客:

http://haohaoxuexi.iteye.com/blog/2157769
http://wiki.jikexueyuan.com/project/spring-security/authenticationProvider.html
http://www.mossle.com/docs/auth/html/index.html


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值