SpringMVC集成RSA加密算法

技术交流群: 233513714

本文介绍的是RSA加密算法+Spring Security在SpringMVC中的集成使用。

Spring Security是什么?

引用:

  Spring Security是一个能够为基于Spring的企业应用系统提供声明式的安全访问控制解决方案的安全框架。它提供了一组可以在Spring应用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反转Inversion of Control ,DI:Dependency Injection 依赖注入)和AOP(面向切面编程)功能,为应用系统提供声明式的安全访问控制功能,减少了为企业系统安全控制编写大量重复代码的工作。

  Spring Security以前叫做acegi,是后来才成为Spring的一个子项目,也是目前最为流行的一个安全权限管理框架,它与Spring紧密结合在一起。

  Spring Security关注的重点是在企业应用安全层为您提供服务,你将发现业务问题领域存在着各式各样的需求。银行系统跟电子商务应用就有很大的不同。电子商务系统与企业销售自动化工具又有很大不同。这些客户化需求让应用安全显得有趣,富有挑战性而且物有所值。Spring Security为基于J2EE的企业应用软件提供了一套全面的安全解决方案。

学习Spring Security的网址http://www.iteye.com/blogs/subjects/spingsecurity3inside。

Spring-Security 自带的加密算法有

- bcrypt
- plaintext
- sha
- sha-256
- md5
- md4
- {sha}
- {ssha}

由于md5加密算法,使用较为普遍,但是可以通过碰撞的方式破解,不采用。

 RSA是什么?

同RSA(Ron Rivest,Adi Shamir,Len Adleman三位天才的名字)一样,ECC(Elliptic Curves Cryptography,椭圆曲线密码编码学)也属于公开密钥算法。但是ECC算法在jdk1.5后加入支持,目前仅仅只能完成密钥的生成与解析。

  RSA是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能被解破的。但在分布式计算和量子计算机理论日趋成熟的今天,RSA加密安全性受到了挑战。RSA算法基于一个十分简单的数论事实:将两个大素数相乘十分容易,但是想要对其乘积进行因式分解却极其困难,因此可以将乘积公开作为加密密钥。

RSA密钥长度随着保密级别提高,增加很快。下表列出了对同一安全级别所对应的密钥长度。


保密级别

对称密钥长度(bit)

RSA密钥长度(bit)

ECC密钥长度(bit)

保密年限

80

80

1024

160

2010

112

112

2048

224

2030

128

128

3072

256

2040

192

192

7680

384

2080

256

256

15360

512

2120

如何实现的RSA+Spring Security 在Spring MVC中的实现,直接上web.xml

xml中的com.user.sec.MyHttpSessionEventPublisher

为自定义的org.springframework.security.web.session.HttpSessionEventPublisher  两者使用其一。

<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:web="http://java.sun.com/xml/ns/javaee" 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_2_5.xsd" metadata-complete="false" version="2.5">
 <!--配置上下文参数,指定spring配置文件的位置 -->  <context-param>
    <param-name>contextConfigLocation</param-name>
    <param-value>classpath*:spring/applicationContext-*.xml</param-value>
  </context-param><!--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><!--Spring 字符集过滤器 --><!--包含设置两个参数encoding和forceEncoding-->
  <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>hibernateFilter</filter-name>
    <filter-class>org.springframework.orm.hibernate4.support.OpenSessionInViewFilter</filter-class>
    <init-param>
      <param-name>excludeSuffixs</param-name>
      <param-value>js,css,jpg,gif</param-value>
    </init-param>
  </filter>
  <filter-mapping>
    <filter-name>hibernateFilter</filter-name>
    <url-pattern>*</url-pattern>
  </filter-mapping>
  <listener>
    <listener-class>org.springframework.web.util.Log4jConfigListener</listener-class>
  </listener>
  <listener>
    <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class>
  </listener>
   <listener>
    <listener-class>com.user.sec.MyHttpSessionEventPublisher</listener-class>
  </listener>
  <!--  <listener>
    <listener-class>org.springframework.security.web.session.HttpSessionEventPublisher</listener-class>
    </listener> -->
  <listener>
    <listener-class>org.springframework.web.util.IntrospectorCleanupListener</listener-class>
  </listener>
  <context-param>
    <param-name>log4jConfigLocation</param-name>
    <param-value>WEB-INF/classes/properties/log4j.properties</param-value>
  </context-param>
  <context-param>
    <param-name>log4jRefreshInterval</param-name>
    <param-value>60000</param-value>
  </context-param>
  <servlet>
    <servlet-name>springmvc</servlet-name>
    <servlet-class>org.springframework.web.servlet.DispatcherServlet</servlet-class>
    <init-param>
      <param-name>contextConfigLocation</param-name>
      <param-value>classpath*:spring/applicationContext-springmvc.xml</param-value>
    </init-param>
    <load-on-startup>1</load-on-startup>
  </servlet>
  <servlet-mapping>
    <servlet-name>springmvc</servlet-name>
    <url-pattern>/</url-pattern>
  </servlet-mapping>
  <filter>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <filter-class>org.springframework.web.filter.HiddenHttpMethodFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>HiddenHttpMethodFilter</filter-name>
    <servlet-name>springmvc</servlet-name>
  </filter-mapping>
  <session-config>
    <session-timeout>30</session-timeout>
  </session-config>
  <welcome-file-list>
    <welcome-file>index.html</welcome-file>
  </welcome-file-list>
  <error-page>
    <error-code>500</error-code>
    <location>/500.html</location>
  </error-page>
</web-app>

applicationContext-security.xml

  Spring Security采用就近原则,有多个约束时,从上至下只要找到第一条满足就返回,因此因该将最严格的约束放在最前面,而将最宽松的约束放在最后面.auto-config属性可以让spring security为我们自动配置几种常用的权限控制机制,包括form,anonymous, rememberMe等。当然你也可以手工配置。例如:<http auto-config="true">

对于拦截pattern的设置,具体如下:

/  所有带/的请求

/* 代表这个域下面的请求  例如:/user/xxx 这种会被拦截  但是不会拦截 /user/xxx/xxx

/** 代表跨域请求  例如:/user/xxx  和 /user/xxx/xxx都会被拦截

<?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.2.xsd
                        http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.2.xsd">

    <global-method-security secured-annotations="enabled" />  <!--配置不过滤的资源,包括登陆请求,静态资源访问,注册页面,获取登陆注册验证码,当然也包括此篇文章所涉及从后台获取的公钥接口-->   <http pattern="/resources/**" security="none" />
    <http pattern="/login.html" security="none" />
    <http pattern="/register.html" security="none" />
    <http pattern="/admin/user/getPairKey" security="none" 
    <http use-expressions="true" auto-config="true">
        <!--允许登录用户操作 -->
        <intercept-url pattern="/pages/**" access="permitAll" />
        <intercept-url pattern="/**" access="isAuthenticated()" />
        <!--所有用户均可使用 -->
        <!-- <intercept-url pattern="/**" access="permitAll" /> -->
        <!-- 允许匿名用户访问 -->
        <!-- <intercept-url pattern="/" access="IS_AUTHENTICATED_ANONYMOUSLY" /> -->
        <!-- <intercept-url pattern="/" access="ROLE_ANONYMOUS" /> -->
        <!-- 验证失败页面 -->
        <form-login login-page="/login.html"
            authentication-failure-url="/login.html?error=true"
            login-processing-url="/j_spring_security_check" default-target-url="/index.html"
            always-use-default-target="true" />
        <!-- 注销页面 -->
        <logout logout-success-url="/login.html" />
        <!-- 记住登陆 -->
        <remember-me key="mpbuser" user-service-ref="userDetailService" />
        <session-management invalid-session-url="/login.html"
            session-authentication-error-url="/login.html">
            <concurrency-control max-sessions="100"
                error-if-maximum-exceeded="false" expired-url="/login.html" />
        </session-management>

        <custom-filter before="FILTER_SECURITY_INTERCEPTOR" ref="myDefineFilter" />
        <!-- 验证权限不足处理类 -->
        <access-denied-handler ref="accessDeniedHandler" />
        <http-basic />
    </http>

    <beans:bean id="encoder"
        class="org.springframework.security.crypto.password.StandardPasswordEncoder" />
    <beans:bean id="RSAEncoder"
        class="com.common.component.util.RSAPasswordEncoder" />
    <authentication-manager alias="authenticationManager"
        erase-credentials="false">
        <authentication-provider user-service-ref="userDetailService">
            <password-encoder ref="RSAEncoder" />
        </authentication-provider>
        <!--自定义Provider -->
        <!-- <authentication-provider ref="myAuthenticationProvider"> </authentication-provider> -->
    </authentication-manager>
    <beans:bean id="myDefineFilter"
        class="com.user.sec.MyFilterSecurityInterceptor">
        <beans:property name="authenticationManager" ref="authenticationManager" />

        <!-- <beans:property name="accessDecisionManager" ref="accessDecisionManager"
            /> -->

        <beans:property name="securityMetadataSource" ref="databaseDefinitionSource" />

        <beans:property name="accessDecisionManager" ref="myAccessDecisionManager" />

    </beans:bean>

    <!-- <beans:bean id="myAuthenticationProvider" class="crowdfunding.user.sec.MyAuthenticationProvider"/> -->
    <beans:bean id="databaseDefinitionSource"
        class="com.user.sec.DefinitionSourceFactoryBean">
        <beans:constructor-arg ref="resourceDetailService" />
        <!-- <beans:constructor-arg ref="userDetailService" /> -->
    </beans:bean>

    <beans:bean id="myAccessDecisionManager"
        class="com.user.sec.MyAccessDecisionManager">
    </beans:bean>

    <beans:bean id="accessDeniedHandler" class="com.user.sec.MyAccessDeniedHandler" />

</beans:beans>

RSAPasswordEncoder.Java

package com.common.component.util;

import java.net.URLDecoder;

import org.apache.commons.lang3.StringUtils;
import org.springframework.security.authentication.encoding.PasswordEncoder;

import Decoder.BASE64Decoder;
import Decoder.BASE64Encoder;
import com.common.component.util.MpbSecureRSAUtil;

/*******************************************************
 * Description:自定义RSA处理类
 *                     如需增加Spring Security 另外的加密方式,重新定义此类<br/>
 ********************************************************/
public class RSAPasswordEncoder implements PasswordEncoder {

    /*****************************************
     * Description:明文加密 <br/>
     * @return
     * @param rawPass
     *            密码
     ******************************************/
    public String encodePassword(String rawPass, Object salt) {

        String encoder = "";
        try {
            encoder = MpbSecureRSAUtil.decryptString(rawPass);
        } catch (Exception e) {

            e.printStackTrace();
        }
        return encoder;
    }

    /*****************************************
     * Description:验证密码是否有效主要是此方法的使用<br/>
     *
     * @return boolean
     ******************************************/
    public boolean isPasswordValid(String encPass, String rawPass, Object salt) {

        if ( !MpbStringUtil.isNotBlank(encPass) || encPass.length() == 0) {
            return false;
        }
        String decPsw = MpbSecureRSAUtil.decryptString(encPass);
        String inpdecPsw = MpbSecureRSAUtil.decryptStringByJs(rawPass);
        try {
            decPsw = URLDecoder.decode(decPsw, "UTF-8");
        } catch (Exception e) {
            e.printStackTrace();
            return  false;
        }
        return inpdecPsw.equals(decPsw);
    }

    /*****************************************
     * Description:私钥解密 <br/>
     *
     * @return
     ******************************************/
    public String decryptPassword(String rawPass, Object salt) {

        String encoder = "";
        try {
            encoder = MpbSecureRSAUtil.decryptString(rawPass);
        } catch (Exception e) {

            e.printStackTrace();
        }
        return encoder;
    }

    /*****************************************
     * Description:Base64解密 <br/>
     * @param key
     * @return
     * @throws Exception
     ******************************************/
    public static byte[] decoderBase64(String key) throws Exception {
        return (new BASE64Decoder()).decodeBuffer(key);
    }

    /*****************************************
     * Description:Base64加密 <br/>
     *
     * @param key
     * @return
     * @throws Exception
     ******************************************/
    public static String encoderBase64(byte[] key) throws Exception {
        return (new BASE64Encoder()).encodeBuffer(key);
    }

}

login.html

<script type="text/javascript" src="resources/js/RSA/security.js"></script>

    function mysubmit() {
         if ($("input[name=‘_spring_security_remember_me‘]").attr("checked") == "checked") {
            //如果记住用户名和密码框被选中则执行remenber()方法
            remember();
        }else{
            //如果未选中则清空cookie
            $.mpbSetCookie("EBS_ISCHECKED", "");
        }
//从后台获取公钥并加密,将加密后的密文传输到服务器处理
        $.mpbPost(
                "/admin/user/getPairKey",
                {
                    "_method" : "GET"
                },
                function(data) {

                    var modulus = data[‘modul‘];
                    var exponent = data[‘exponent‘];
                    var key = RSAUtils.getKeyPair(exponent, ‘‘, modulus);
                    var pwd = $("#psw").val();
                    pwd = encodeURIComponent(pwd);
                    pwd = RSAUtils.encryptedString(key, pwd);
                    //$("#psw").attr("value",pwd);
                    $("input[name=‘j_password‘]").val(pwd);
                    $("#myform").submit();
                });

    }

Controler.Java

@ResponseBody
    @RequestMapping(value = "/getPairKey", method = RequestMethod.GET)
    public Map<?,?> getKey() throws Exception {
        RSAPublicKey publicKey = MpbSecureRSAUtil.getDefaultPublicKey();

        Map<String, String> key = new HashMap<String,String>();

        key.put("modul",
                new String(Hex.encodeHex(publicKey.getModulus().toByteArray())));
        key.put("exponent",
                new String(Hex.encodeHex(publicKey.getPublicExponent()
                        .toByteArray())));

        return key;
    }

文件地址:

http://files.cnblogs.com/files/Sonet-life/security.js

http://files.cnblogs.com/files/Sonet-life/MpbSecureRSAUtil.rar

整个加密的思路:

1、项目在启动时就检查是否生成密钥对文件,没有就强制生成新的,记住利用RSA注册的用户在数据库保存的是加密后的密文,RSA密钥对文件要保证一致性,如果密钥对文件生成了新的,而且你没备份之前的密钥对文件,将会造成不可挽回的后果。最好的方法,通过对MpbSecureRSAUtil中密钥对文件的生成路径设置成硬盘下的,不要放到Tomcat服务器中,否则每次你删除项目的时候,或者重新部署都会造成密钥对文件的重新生成。或者每次都用旧的替换新生成的,保持可用性。

2、前台请求服务器的公钥,传输到前台,因为公钥是公开的,使用公钥在前台加密用户登录注册或者其他保密的信息,将公钥加密的密文传输到服务器。服务器通过与公钥对应的私钥,解密数据库的密文和传输过来的密文,将解密后的字符相比较,再将确认信息返回到前台,进行下一步的操作。

时间: 2024-08-28 12:08:34

SpringMVC集成RSA加密算法的相关文章

RSA加密算法的简单案例

RSA加密算法是目前最有影响力的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击. 那关于RSA加密算法有哪些应用呢?以下举一个数据库身份验证的案例. 在使用数据集进行身份认证时,密码存在数据库中,认证时用户输入的密码与数据库中密码相同则认证通过,若数据库被破解了则对系统造成威胁,怎样保证系统安全呢?这里就可以应用RSA加密算法,对权限加密. 思路: 就是在url中传用户名密码时,先把用户名进行翻转,然后再进行加密,如输入的密码为12,实际后台进行加密的值为21,再与数据库进行验证,这样

Springmvc集成Shiro实现权限管理

Shiro是一个安全框架,他可以集成其他开发开发框架 如:Springmvc,实现用户身份认证.权限管理等等功能,shiro详细的介绍也就不讲了,这里给出一些关键的知识点吧: 知识点: shiro中默认的过滤器 过滤器名称 过滤器类 描述 anon org.apache.shiro.web.filter.authc.AnonymousFilter 匿名过滤器 authc org.apache.shiro.web.filter.authc.FormAuthenticationFilter 如果继续

Java使用RSA加密算法对内容进行加密

什么是RSA加密算法 RSA是一种典型的非对称性加密算法,具体介绍可参考阮一峰的日志 RSA算法原理 下面是使用RSA算法对传输内容进行加密的一个简要Java案例,主要用到了三个类,大体实现如下: 对内容进行RSA加密和解密校验的类 import java.security.KeyFactory; import java.security.PrivateKey; import java.security.PublicKey; import java.security.spec.PKCS8Enco

RSA加密算法的加密与解密

转发原文链接:RSA加密算法加密与解密过程解析 1.加密算法概述 加密算法根据内容是否可以还原分为可逆加密和非可逆加密. 可逆加密根据其加密解密是否使用的同一个密钥而可以分为对称加密和非对称加密. 所谓对称加密即是指在加密和解密时使用的是同一个密钥:举个简单的例子,对一个字符串C做简单的加密处理,对于每个字符都和A做异或,形成密文S.解密的时候再用密文S和密钥A做异或,还原为原来的字符串C.这种加密方式有一个很大的缺点就是不安全,因为一旦加密用的密钥泄露了之后,就可以用这个密钥破解其他所有的密文

RSA加密算法正确性证明

RSA加密算法是利用大整数分解耗时非常大来保证加密算法不被破译. 密钥的计算过程为:首先选择两个质数p和q,令n=p*q. 令k为n的欧拉函数,k=?(n)=(p−1)(q−1) 选择任意整数a,保证其与k互质 取整数b,使得a*b ≡1mod k 令公匙为a和n.私匙为p,q,b. 加密时算法为: 例如所发数位x,则所发过去的数据为 o = x^a mod n 解码时将可以得到x = o^b 正确性证明(1):?(n)=(p−1)(q−1) 成立的正确性 ?(n)表示小于n且与n互质数的个数

Android应用开发中如何使用RSA加密算法对数据进行校验

这个世界很精彩,这个世界很无奈.是的,在互联网时代,如何保护自己的数据,如何对数据进行加密和效验就变得非常的重要.这里总结一下Android平台使用Java语言,利用RSA算法对数据进行校验的经验. 先来看下如何RSA加密算法对数据进行校验的流程: 1.首先要用openssh之类的程序生成一个私钥 2.再根据私钥生成一个公钥 3.使用私钥和公钥,对数据进行签名,得到签名文件. 4.使用公钥和签名文件就可以对数据进行校验了. 再来看下如何实现: 1.生成2048位的私钥: openssl genr

轻松学习RSA加密算法原理

以前也接触过RSA加密算法,感觉这个东西太神秘了,是数学家的事,和我无关.但是,看了很多关于RSA加密算法原理的资料之后,我发现其实原理并不是我们想象中那么复杂,弄懂之后发现原来就只是这样而已.. 学过算法的朋友都知道,计算机中的算法其实就是数学运算.所以,再讲解RSA加密算法之前,有必要了解一下一些必备的数学知识.我们就从数学知识开始讲解. 必备数学知识 RSA加密算法中,只用到素数.互质数.指数运算.模运算等几个简单的数学知识.所以,我们也需要了解这几个概念即可. 素数 素数又称质数,指在一

spring+springMVC集成(annotation方式)

spring+springMVC集成(annotation方式) SpringMVC+Spring4.0+Hibernate 简单的整合 MyBatis3整合Spring3.SpringMVC3

RSA加密算法加密与解密过程解析

1.加密算法概述 加密算法根据内容是否可以还原分为 可逆加密和非可逆加密 . 可逆加密根据其加密解密是否使用的同一个密钥而可以分为 对称加密和非对称加密. 所谓对称加密即是指在加密和解密时使用的是同一个密钥:举个简单的例子,对一个字符串C做简单的加密处理,对于每个字符都和A做异或,形成密文S.解密的时候再用密文S和密钥A做异或,还原为原来的字符串C.这种加密方式有一个很大的缺点就是不安全,因为一旦加密用的密钥泄露了之后,就可以用这个密钥破解其他所有的密文. 非对称加密在加密和解密过程中使用不同的