`

spring security 提供系统安全功能

阅读更多

1.概述

     由于 spring security 是在权限系统开发关闭后补上去的所以只使用了 spring security 中的提供的一部分内容;

完成功能包括:用户校验、注销功能、Session 失效处理、防止一个用户同一时间内多次登录系统、保护系统资源(防止绕过登录访问资源)。

 

2.代码片段

 

<?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-2.5.xsd
            http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-2.0.4.xsd">
	
	<!-- http安全配置 -->
	<http servlet-api-provision="true">
		<intercept-url pattern="/**/*.jpg" filters="none"/>
	    <intercept-url pattern="/**/*.png" filters="none"/>
	    <intercept-url pattern="/**/*.gif" filters="none"/>
	    <intercept-url pattern="/**/*.css" filters="none"/>
	    <intercept-url pattern="/**/*.js" filters="none"/>
		
		<intercept-url pattern="/servlet/CheckLoginCodeServlet" filters="none"/>
		<intercept-url pattern="/servlet/SessionImage" filters="none"/>
		<intercept-url pattern="/login/login.jsp" filters="none"/>
		<intercept-url pattern="/login/logout.jsp" filters="none"/>
		<intercept-url pattern="/**" access="ROLE_ADMIN"/>
		<form-login login-page="/login/login.jsp" 
			authentication-failure-url="/login/login.jsp" 
			default-target-url="/login.do"
			always-use-default-target="true"/>
		<logout/>
		<concurrent-session-control/>
	</http>
	
	<beans:bean id="jaasAuthenticationProvider"
	    class="org.springframework.security.providers.jaas.JaasAuthenticationProvider">
	    <custom-authentication-provider/>
	    <beans:property name="loginConfig" value="/WEB-INF/login.conf" />
	    <beans:property name="loginContextName" value="JAASTest" />
	    <beans:property name="callbackHandlers">
	        <beans:list>
	            <beans:bean class="org.springframework.security.providers.jaas.JaasNameCallbackHandler" />
	            <beans:bean class="org.springframework.security.providers.jaas.JaasPasswordCallbackHandler" />
	        </beans:list>
	    </beans:property>
	    <beans:property name="authorityGranters">
	        <beans:list>
	            <beans:bean class="com.hw.msds.login.businessimp.AuthorityGranterImpl" />
	        </beans:list>
	    </beans:property>
	</beans:bean>

	<beans:bean id="sessionTimeoutFilter" class="com.hw.msds.login.businessimp.SessionTimeoutFilter">
		<custom-filter before="CONCURRENT_SESSION_FILTER" />
	</beans:bean>
</beans:beans>
 
<form method="post" action="<%=basePath%>j_spring_security_check" onsubmit="return loginsubmit();">


用户名: <input id="j_username" name="j_username" type="text"  class="user" />
密&nbsp;&nbsp;码:<input id="j_password" name="j_password" type="password"  class="user" />

<input id="submitbtn" type="submit" value="登 录" class="btn_login"/>

</form>

 
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%>
<%
String path = request.getContextPath();
String basePath = request.getScheme()+"://"+request.getServerName()+":"+request.getServerPort()+path+"/";
%>

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <base href="<%=basePath%>">
    
    <title>登出</title>
    
	<meta http-equiv="pragma" content="no-cache">
	<meta http-equiv="cache-control" content="no-cache">
	<meta http-equiv="expires" content="0">    
	<script type="text/javascript">
		function init() {
			window.top.location.target="_top";
			window.top.location.href="j_spring_security_logout";
		}
		window.onload=init;
	</script>
  </head>
  
  <body>
  	session失效请 <a href="j_spring_security_logout" target="_top">重新登录</a>
  </body>
</html>
 
JAASTest {
    com.hw.msds.login.businessimp.LoginModuleImpl required
    driver="oracle.jdbc.driver.OracleDriver"
    url="jdbc:oracle:thin:msds/msds@192.168.1.154:1521:msds"
    db_username="msds"
    db_password="msds"
    debug="true";
};
 
import java.security.Principal;
import java.util.HashSet;
import java.util.Set;
import org.springframework.security.providers.jaas.AuthorityGranter;

public class AuthorityGranterImpl implements AuthorityGranter {
    public Set grant(Principal principal) {
        Set rtnSet = new HashSet();
        if (principal.getName().equals("TEST_PRINCIPAL")) {
            rtnSet.add("ROLE_ADMIN");
        }
        return rtnSet;
    }
}
 
import java.security.Principal;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Map;

import javax.security.auth.Subject;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.NameCallback;
import javax.security.auth.callback.PasswordCallback;
import javax.security.auth.callback.TextInputCallback;
import javax.security.auth.login.LoginException;
import javax.security.auth.spi.LoginModule;

import org.springframework.security.context.SecurityContextHolder;

import com.hw.msds.base.sys.Password;
import com.hw.msds.base.sys.SystemBuffer;
import com.hw.msds.base.util.DB;

public class LoginModuleImpl implements LoginModule {
	
	private Subject subject;
	private CallbackHandler callbackHandler;
	private Map sharedState;
	private Map options;
	
	private String url;
	private String driver;
	private String db_username;
	private String db_password;
	
    private String password;
    private String user;
    

    public boolean abort() throws LoginException {
        return true;
    }

    public boolean commit() throws LoginException {
        return true;
    }

    public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
        this.subject = subject;
        this.callbackHandler = callbackHandler;
        this.sharedState = sharedState;
        this.options = options;
        
        url = (String)options.get("url");
        driver = (String)options.get("driver");
        db_username = (String)options.get("db_username");
        db_password = (String)options.get("db_password");

        try {
            TextInputCallback textCallback = new TextInputCallback("prompt");
            NameCallback nameCallback = new NameCallback("prompt");
            PasswordCallback passwordCallback = new PasswordCallback("prompt", false);
            callbackHandler.handle(new Callback[] {textCallback, nameCallback, passwordCallback});
            
            password = new String(passwordCallback.getPassword());
            user = nameCallback.getName();
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    public boolean login() throws LoginException {
    	System.out.println("driver " + driver);
    	System.out.println("url " + url);
    	System.out.println("db_username " + db_username);
    	System.out.println("db_password " + db_password);
    	
    	System.out.println("user " + user);
    	System.out.println("password " + password);
    	
    	String dpwd="";
    	String dtype="";
    	boolean flag=false;
    	
    	// 校验用户
    	String sql = "select tp.name, tps.secretcode, tc.type from tperson tp inner join tcorp tc on tp.corpid = tc.objid inner join tpersonpsw tps on tp.objid = tps.objid where tp.name = ?";
    	Connection conn = DB.getConnection(driver, url, db_username, db_password);
    	PreparedStatement stat = null;
		ResultSet rs = null;
		try {
			stat = conn.prepareStatement(sql);
			stat.setString(1, user);
			rs = stat.executeQuery();
			
			while (rs != null && rs.next()) {
				dpwd = rs.getString("secretcode");
				dtype = rs.getString("type");
				flag = true;
			}
		} catch (SQLException e) {
			e.printStackTrace();
		} finally {
			try {
				if (rs != null) {
					rs.close();
				}
				if (stat != null) {
					stat.close();
				}
			} catch (SQLException e) {
				e.printStackTrace();
			}
		}
    	DB.closeConnection(conn);
    	
		if (flag == false) {
			throw new LoginException("用户名不存在!");
		}
		
		if (!dpwd.equals(Password.createPassword(password))) {
			throw new LoginException("密码错误!");
		}
		SystemBuffer.userInfo.put(user + "_password", dpwd);
		SystemBuffer.userInfo.put(user + "_logintype", dtype);
		
		
		subject.getPrincipals().add(new Principal() {
			public String getName() {
				return "TEST_PRINCIPAL";
			}
		});
		return true;
    }

    public boolean logout() throws LoginException {
        return true;
    }
}
 
import java.io.IOException;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;

import org.springframework.security.ui.AbstractProcessingFilter;
import org.springframework.security.ui.SpringSecurityFilter;
import org.springframework.security.ui.savedrequest.SavedRequest;
import org.springframework.security.util.PortResolver;
import org.springframework.security.util.PortResolverImpl;

public class SessionTimeoutFilter extends SpringSecurityFilter {
    private PortResolver portResolver = new PortResolverImpl();
    private String sessionTimeoutUrl;

    public void doFilterHttp(HttpServletRequest request,
        HttpServletResponse response, FilterChain chain)
        throws IOException, ServletException {
        if (this.isSessionExpired(request)) {
        	System.out.println("!!!!!!!!!!!!!!!!!!!!!!!! session过期");
            this.processRequest(request, response);
        } else {
            chain.doFilter(request, response);
        }
    }

    protected String determineSessionTimeoutUrl(HttpServletRequest request) {
        return (sessionTimeoutUrl != null) ? sessionTimeoutUrl  : "/login/logout.jsp";
    }

    protected boolean isSessionExpired(HttpServletRequest request) {
        return (request.getRequestedSessionId() != null)
        && !request.isRequestedSessionIdValid();
    }

    protected void processRequest(HttpServletRequest request,
        HttpServletResponse response) throws IOException {
        HttpSession session = request.getSession();
        SavedRequest savedRequest = new SavedRequest(request, portResolver);
        session.setAttribute(AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY, new RuntimeException("连接超时,如果需要继续操作请重新登录系统!"));
        session.setAttribute(AbstractProcessingFilter.SPRING_SECURITY_SAVED_REQUEST_KEY, savedRequest);
        String targetUrl = determineSessionTimeoutUrl(request);
        
        targetUrl = request.getContextPath() + targetUrl;
        response.sendRedirect(response.encodeRedirectURL(targetUrl));
    }

	public int getOrder() {
		return 0;
	}
}

 3.说明

a. 用户校验和用户信息加载

     我是用了JAAS进行用户名密码校验,所有校验成功的用户都被分配了ROLE_ADMIN角色,校验失败抛出异常。

     校验成功后我指定了程序跳转至login.do,login.do作用就是加载用户相关信息(包括用户所属部门、所属公司、可操作的模块以及对应的权限信息)

b. 系统注销

     login.do 判断如果是注销,清空当前用户session,并转向 j_spring_security_logout 。

c. Session 失效处理

     详见 SessionTimeoutFilter.java ,   判断是否有 sessionid 存在如果存在判断是否过期,如果过期则调整至登录页面并给出提示信息,如果没有sessionid说明用户未登录过不错任何处理。

d. 防止一个用户同一时间内多次登录系统

     spring security 提供的功能    详见<concurrent-session-control/>

e. 保护系统资源(防止绕过登录访问资源)

     详见 <http> 部分, 注意当用户身份校验成功后,就会被赋予ROLE_ADMIN角色,意味着这他就能够访问所有页面(给个用户访问权限内的所有页面)

 

4.标注

     上面是我在最近项目中web安全方面的的一点点经验,希望大家多提建议。

 

参考文献:

spring security 安全开发手册

http://www.family168.com/oa/springsecurity/html/index.html

 

1
1
分享到:
评论

相关推荐

    SpringSecurity.pdf

    通过配置Maven坐标,开发者可以在项目中引入Spring Security,从而开始安全功能的配置与开发。此外,Spring Security还提供了一个快速入门案例,帮助初学者理解如何通过配置来保护应用程序的资源。 Spring Security...

    Spring Security 资料合集

    Spring Security 是一个强大的安全框架,主要用于Java应用的安全管理,它为Web应用和企业级应用提供了全面的安全服务。这个框架能够处理认证、授权以及各种安全相关的功能,帮助开发者构建安全、可扩展的应用。以下...

    spring security 完整项目实例

    最后,Spring Security提供了丰富的日志和审计功能,帮助开发者追踪和理解系统的安全行为。 总之,这个"spring security 完整项目实例"涵盖了Spring Security的核心组件和用法,包括用户管理、身份验证、权限控制、...

    spring security 官方文档

    Spring Security 是一个强大的安全框架,用于为Java应用提供全面的安全管理解决方案。它是Spring生态系统的组成部分,专注于身份验证、授权和访问控制。Spring Security的核心特性包括: 1. **身份验证...

    SpringSecurity笔记,编程不良人笔记

    - **Filter Chain**: SpringSecurity通过一系列过滤器实现其安全功能,这些过滤器构成了Filter Chain。每个过滤器负责特定的安全任务,如认证、授权等。 - **Authentication**: 表示用户的身份信息,包括用户名、...

    Spring Security3 安全 个人总结

    Spring Security3 是一个功能强大且灵活的安全框架,提供了一个全面的安全机制来保护基于 Spring 的应用程序。通过理解 Spring Security3 的安全机制、原理和核心组件,我们可以更好地使用 Spring Security3 来保护...

    SpringSecurity.zip

    充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的...

    spring security3 中文版本

    Spring Security 的目标是使开发人员能够快速地为应用程序添加安全功能,同时提供足够的灵活性来满足特定需求。 ##### 1.2 历史 Spring Security 的前身是 Acegi Security,它于 2004 年发布。2006 年,Acegi 被...

    Spring Cloud Gateway 整合 Spring Security 统一登录认证鉴权

    总的来说,将Spring Cloud Gateway与Spring Security相结合,可以构建出一套高效、安全的微服务认证系统,提高整体系统的稳定性和用户体验。这种整合不仅简化了微服务之间的交互,还增强了系统的安全性,是现代...

    精彩:Spring Security 演讲PPT

    Spring Security 是一个功能强大的安全框架,可以为基于Java的应用程序提供认证(Authentication)、授权(Authorization)等功能,同时提供了丰富的配置选项来满足不同的应用场景需求。 #### 二、传统Web应用安全开发...

    spring-security 官方文档 中文版

    Spring Security 是一款基于 Spring 框架的安全插件,提供了完整的安全性解决方案,包括身份认证(Authentication)、授权(Authorization)以及会话管理(Session Management)等功能。Spring Security 的设计目标是为...

    spring_security_3.1

    4. **会话管理**:Spring Security提供了会话管理功能,如会话固定保护、会话超时和并发会话控制。这在防止会话劫持和会话固定攻击方面至关重要。 5. **CSRF(跨站请求伪造)防护**:Spring Security 3.1默认提供了...

    springSecurity 实现传参

    5. **数据库集成**:对于MySQL的建库脚本,Spring Security可以与任何数据库系统集成,包括MySQL。你需要创建一个用户表来存储用户名和密码(通常经过哈希和盐值处理),可能还有角色和其他权限信息。Spring ...

    (源码)基于Spring Security框架的安全认证与授权系统.zip

    本项目是一个基于Spring Security框架的安全认证与授权系统,旨在提供一个可复用的脚手架,帮助开发者快速实现认证授权机制。项目支持常见的认证、授权机制,如OAuth 2.0、JWT等,并提供了多种验证码功能(如图片...

    SpringSecurity退出功能实现的正确方式(推荐)

    Spring Security 框架提供了强大的安全功能,其中退出功能是非常重要的一部分。本文将介绍如何正确地实现 Spring Security 退出功能。 一、logout 最简及最佳实践 使用 Spring Security 实现 logout 功能非常简单...

    安全框架Spring Security深入浅出视频教程

    视频详细讲解,需要的小伙伴自行网盘下载,链接见附件,永久有效。 首先,SSM环境中我们通过xml配置的...Springsecurity在两种不同的开发模式中使用,有经典的独立web后台管理系统,也有时下最流行的前后端分离场景。

    SpringBoot+SpringSecurity+WebSocket

    接着,SpringSecurity是Spring生态系统中的安全模块,用于实现身份验证和授权。它提供了一套全面的安全解决方案,包括登录认证、权限控制、CSRF保护等。在"SpringBoot+SpringSecurity"的组合中,SpringSecurity负责...

    spring security 安全权限管理手册

    Spring Security 提供了一组 JSP 标签库,可以帮助开发者更容易地在视图层实现安全相关的功能。 **5.1 配置 taglib** 在 JSP 文件中使用这些标签前,需要先配置 `&lt;%@ taglib %&gt;` 指令。 **5.2 authentication** ...

    基本的spring mvc + spring security实现的登录(无数据库)

    在本项目中,我们主要探讨的是如何利用Spring MVC和Spring Security框架构建一个基本的无数据库登录系统。Spring MVC是Spring框架的一部分,用于处理Web应用程序的请求-响应模型,而Spring Security则是一个强大的...

    springsecurity原理流程图.pdf

    Spring Security 是一个功能强大且高度可定制的身份验证和访问控制框架,它是安全领域中Spring生态系统的一部分。Spring Security旨在为Java应用程序提供一个全面的安全解决方案,尤其适用于企业级应用场景。它主要...

Global site tag (gtag.js) - Google Analytics