Jeesite单点登录集成Cas另加自定义登录验证

来源:互联网 发布:knn算法 matlab 编辑:程序博客网 时间:2024/05/23 13:51

Jeesite单点登录集成Cas另加自定义登录验证

标签: jeesitecas单点登录自定义加密自定义验证规则
1464人阅读 评论(9)收藏举报
本文章已收录于:
分类:
作者同类文章X

    目录(?)[+]

    1. Jeesite单点登录集成Cas另加自定义登录验证
      1. Cas基础
        1. 服务端
        2. 默认登录用户名密码
        3. 去除https
        4. 修改客户端应用的webxml
      2. Jeesite单点登录集成cas
        1. 需要写个自己MyCasRealmjava
        2. 修改spring-context-shiroxml配置文件
        3. 新增配置bean casRealm
        4. 修改Shiro安全管理配置的realm属性
        5. Jeesite其它
        6. Cas通过查询数据库验证用户名密码正确性密码非复杂加密可如MD5SHA-1等
          1. jar包准备
          2. 编辑WEB-INFdeployerConfigContextxml加入数据源
        7. Cas服务端二次开发
          1. 把cas-server-webapp-400war转换成Eclipse项目
          2. 自定义登录验证加密规则
            1. 复制jeesite的3个java文件
            2. jar包
            3. 开发自己的MyQueryDatabaseAuthenticationHandlerjava
            4. 修改deployerConfigContextxml文件
          3. jeesite加密研究
          4. 其它方式实现单点登录

    Jeesite单点登录集成Cas另加自定义登录验证

    JeeSite是基于多个优秀的开源项目,高度整合封装而成的高效,高性能,强安全性的 开源 Java EE快速开发平台.

    Cas主要是用来解决多应用之间统一登陆认证,无需用户在同一公司多应用之间重复登陆。例如阿里巴巴中淘宝、天猫,在多个应用系统中,用户只需要登录一次就可以访问所有相互信任的应用系统.


    Cas基础

    服务端

    服务端cas-server-webapp-4.0.0.war,服务器端程序一般不用我们完成,但需要做一点小小的修改,cas的服务器端程序由spring+Spring web flow+cas写成。全部使用spring配置文件。

    默认登录用户名密码

    这里写图片描述


    去除https

    修改第一处: cas/WEB-INF/deployerConfigContext.xml

    <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler"p:httpClient-ref="httpClient"/>
    • 1
    • 2
    • 1
    • 2

    增加参数p:requireSecure=”false”,是否需要安全验证,即HTTPS,false为不采用。修改后为:

    <bean class="org.jasig.cas.authentication.handler.support.HttpBasedServiceCredentialsAuthenticationHandler" p:httpClient-ref="httpClient"   p:requireSecure="false"/>
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    修改第二处: cas/WEB-INF/spring-configuration/ticketGrantingTicketCookieGenerator.xml

    <bean id="ticketGrantingTicketCookieGenerator" class="org.jasig.cas.web.support.CookieRetrievingCookieGenerator"      p:cookieSecure="true"      p:cookieMaxAge="-1"      p:cookieName="CASTGC"      p:cookiePath="/cas" />
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    参数p:cookieSecure=”true”,同理为HTTPS验证相关,TRUE为采用HTTPS验证,FALSE为不采用https验证。

    参数p:cookieMaxAge=”-1”,简单说是COOKIE的最大生命周期,-1为无生命周期,即只在当前打开的IE窗口有效,IE关闭或重新打开其它窗口,仍会要求验证。可以根据需要修改为大于0的数字,比如3600等,意思是在3600秒内,打开任意IE窗口,都不需要验证。
    这里把 cookieSecure修改为false就行了

    修改客户端应用的web.xml

    增加如下filter和mapping(jeesite不修改此处,有其它方式处理)

     <filter>   <filter-name>CAS Authentication Filter</filter-name>   <filter-class>    org.jasig.cas.client.authentication.AuthenticationFilter   </filter-class>   <init-param>    <param-name>casServerLoginUrl</param-name>    <param-value>    http://localhost:8080/cas/login    </param-value>   </init-param>   <init-param>    <param-name>renew</param-name>    <param-value>false</param-value>   </init-param>   <init-param>    <param-name>gateway</param-name>    <param-value>false</param-value>   </init-param>   <init-param>    <param-name>serverName</param-name>    <param-value>http://localhost:8080</param-value>   </init-param></filter><filter>   <filter-name>CAS Validation Filter</filter-name>   <filter-class>    org.jasig.cas.client.validation.Cas20ProxyReceivingTicketValidationFilter   </filter-class>   <init-param>    <param-name>casServerUrlPrefix</param-name>    <param-value>http://localhost:8080/cas</param-value>   </init-param>   <init-param>    <param-name>serverName</param-name>    <param-value>http://localhost:8080</param-value>   </init-param>   <init-param>    <param-name>useSession</param-name>    <param-value>true</param-value>   </init-param>   <init-param>    <param-name>redirectAfterValidation</param-name>    <param-value>true</param-value>   </init-param></filter><filter>   <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>   <filter-class>    org.jasig.cas.client.util.HttpServletRequestWrapperFilter   </filter-class></filter><filter>   <filter-name>CAS Assertion Thread Local Filter</filter-name>   <filter-class>    org.jasig.cas.client.util.AssertionThreadLocalFilter   </filter-class></filter><filter>        <filter-name>loginFilter</filter-name>        <filter-class>org.springframework.web.filter.DelegatingFilterProxy</filter-class>        <init-param>            <param-name>targetFilterLifecycle</param-name>            <param-value>true</param-value>        </init-param>    </filter><filter-mapping>   <filter-name>CAS Authentication Filter</filter-name>   <url-pattern>/*</url-pattern></filter-mapping><filter-mapping>   <filter-name>CAS Validation Filter</filter-name>   <url-pattern>/*</url-pattern></filter-mapping><filter-mapping>   <filter-name>CAS HttpServletRequest Wrapper Filter</filter-name>   <url-pattern>/*</url-pattern></filter-mapping><filter-mapping>   <filter-name>CAS Assertion Thread Local Filter</filter-name>   <url-pattern>/*</url-pattern></filter-mapping>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88

    Jeesite单点登录集成cas

    需要写个自己MyCasRealm.java

    package com.thinkgem.jeesite.modules.sys.security;import java.util.Collection;import java.util.List;import org.apache.commons.lang3.StringUtils;import org.apache.shiro.authc.AuthenticationException;import org.apache.shiro.authc.AuthenticationInfo;import org.apache.shiro.authc.AuthenticationToken;import org.apache.shiro.authc.SimpleAuthenticationInfo;import org.apache.shiro.authz.AuthorizationInfo;import org.apache.shiro.authz.SimpleAuthorizationInfo;import org.apache.shiro.cas.CasAuthenticationException;import org.apache.shiro.cas.CasRealm;import org.apache.shiro.cas.CasToken;import org.apache.shiro.session.Session;import org.apache.shiro.subject.PrincipalCollection;import org.apache.shiro.subject.SimplePrincipalCollection;import org.jasig.cas.client.authentication.AttributePrincipal;import org.jasig.cas.client.validation.Assertion;import org.jasig.cas.client.validation.TicketValidationException;import org.jasig.cas.client.validation.TicketValidator;import org.slf4j.Logger;import org.slf4j.LoggerFactory;import com.thinkgem.jeesite.common.config.Global;import com.thinkgem.jeesite.common.utils.SpringContextHolder;import com.thinkgem.jeesite.common.web.Servlets;import com.thinkgem.jeesite.modules.sys.entity.Menu;import com.thinkgem.jeesite.modules.sys.entity.Role;import com.thinkgem.jeesite.modules.sys.entity.User;import com.thinkgem.jeesite.modules.sys.security.SystemAuthorizingRealm.Principal;import com.thinkgem.jeesite.modules.sys.service.SystemService;import com.thinkgem.jeesite.modules.sys.utils.LogUtils;import com.thinkgem.jeesite.modules.sys.utils.UserUtils;public class MyCasRealm extends CasRealm {    private Logger logger = LoggerFactory.getLogger(getClass());    private SystemService systemService;    @Override    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {//      return super.doGetAuthenticationInfo(token);        CasToken casToken = (CasToken) token;        if (token == null) {            return null;        }        //获取ticket        String ticket = (String)casToken.getCredentials();        if (!org.apache.shiro.util.StringUtils.hasText(ticket)) {            return null;        }        TicketValidator ticketValidator = ensureTicketValidator();        try {            //回传ticket到服务端验证,验证通过就进入下一行,可以获取登录后的相关信息,否则直接抛异常,即验证不通过            Assertion casAssertion = ticketValidator.validate(ticket, getCasService());            AttributePrincipal casPrincipal = casAssertion.getPrincipal();            String userId = casPrincipal.getName();            User user = getSystemService().getUserByLoginName(userId);            if (user != null) {                Principal p = new  Principal(user, false);                PrincipalCollection principalCollection = new SimplePrincipalCollection(p, getName());                return new SimpleAuthenticationInfo(principalCollection, ticket);            } else {                return null;            }        } catch (TicketValidationException e) {             throw new CasAuthenticationException("Unable to validate ticket [" + ticket + "]", e);        }    }    @Override    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) {        Principal principal = (Principal) getAvailablePrincipal(principals);        // 获取当前已登录的用户        if (!Global.TRUE.equals(Global.getConfig("user.multiAccountLogin"))){            Collection<Session> sessions = getSystemService().getSessionDao().getActiveSessions(true, principal, UserUtils.getSession());            if (sessions.size() > 0){                // 如果是登录进来的,则踢出已在线用户                if (UserUtils.getSubject().isAuthenticated()){                    for (Session session : sessions){                        getSystemService().getSessionDao().delete(session);                    }                }                // 记住我进来的,并且当前用户已登录,则退出当前用户提示信息。                else{                    UserUtils.getSubject().logout();                    throw new AuthenticationException("msg:账号已在其它地方登录,请重新登录。");                }            }        }        User user = getSystemService().getUserByLoginName(principal.getLoginName());        if (user != null) {            SimpleAuthorizationInfo info = new SimpleAuthorizationInfo();            List<Menu> list = UserUtils.getMenuList();            for (Menu menu : list){                if (StringUtils.isNotBlank(menu.getPermission())){                    // 添加基于Permission的权限信息                    for (String permission : StringUtils.split(menu.getPermission(),",")){                        info.addStringPermission(permission);                    }                }            }            // 添加用户权限            info.addStringPermission("user");            // 添加用户角色信息            for (Role role : user.getRoleList()){                info.addRole(role.getEnname());            }            // 更新登录IP和时间            getSystemService().updateUserLoginInfo(user);            // 记录登录日志            LogUtils.saveLog(Servlets.getRequest(), "系统登录");            return info;        } else {            return null;        }    }    /**     * 获取系统业务对象     */    public SystemService getSystemService() {        if (systemService == null){            systemService = SpringContextHolder.getBean(SystemService.class);        }        return systemService;    }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135

    修改spring-context-shiro.xml配置文件

    原来的:

    <property name="loginUrl" value="${adminPath}/login" />
    • 1
    • 1

    改为:

    <property name="loginUrl" value="${cas.server.url}?service=${cas.project.url}${adminPath}/cas" />
    • 1
    • 2
    • 3
    • 1
    • 2
    • 3

    其实就是把注释放开

    新增配置bean : casRealm

    <bean id="casRealm" class="com.thinkgem.jeesite.modules.sys.security.MyCasRealm">        <property name="casServerUrlPrefix" value="${cas.server.url}"/>        <!-- 客户端的回调地址设置,必须和下面的shiro-cas过滤器拦截的地址一致 -->        <property name="casService" value="${cas.project.url}${adminPath}/cas"/></bean>
    • 1
    • 2
    • 3
    • 4
    • 5
    • 1
    • 2
    • 3
    • 4
    • 5

    修改Shiro安全管理配置的realm属性

    原来Shiro安全管理配置的realm属性:

    <property name="realm" ref="systemAuthorizingRealm" />
    • 1
    • 1

    改为:<property name="realm" ref="casRealm" />


    Jeesite其它

    其他的基本没有什么修改的,要改的话就是:jeesite.properties里面的cas.project.url和cas.server.url

    这里写图片描述

    Cas通过查询数据库验证用户名、密码正确性(密码非复杂加密,可如:MD5,SHA-1等)

    jar包准备

    MySQL jdbc驱动:mysql-connector-Java-5.1.13-bin.jar
    Cas jdbc支持:cas-server-support-jdbc-4.0.0.jar

    编辑:WEB-INF\deployerConfigContext.xml,加入数据源:

    这里写图片描述

    这里写图片描述

    Cas服务端二次开发

    把cas-server-webapp-4.0.0.war转换成Eclipse项目

    这里写图片描述

    自定义登录验证(加密规则)

    复制jeesite的3个java文件

    作用是在Cas服务端实现jeesite的密码加密方式

    这里写图片描述

    jar包

    这里写图片描述

    开发自己的MyQueryDatabaseAuthenticationHandler.java

    package com.jinfonet.developer.portal;import java.security.GeneralSecurityException;import org.jasig.cas.adaptors.jdbc.AbstractJdbcUsernamePasswordAuthenticationHandler;import org.jasig.cas.authentication.HandlerResult;import org.jasig.cas.authentication.PreventedException;import org.jasig.cas.authentication.UsernamePasswordCredential;import org.jasig.cas.authentication.principal.SimplePrincipal;import org.springframework.dao.DataAccessException;import org.springframework.dao.IncorrectResultSizeDataAccessException;import com.thinkgem.jeesite.common.security.Digests;import com.thinkgem.jeesite.common.utils.Encodes;import javax.security.auth.login.AccountNotFoundException;import javax.security.auth.login.FailedLoginException;import javax.validation.constraints.NotNull;/** * 20170309gch */public class MyQueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler {    public static final String HASH_ALGORITHM = "SHA-1";    public static final int HASH_INTERATIONS = 1024;    public static final int SALT_SIZE = 8;    @NotNull    private String sql;    /** {@inheritDoc} */    @Override    protected final HandlerResult authenticateUsernamePasswordInternal(final UsernamePasswordCredential credential)            throws GeneralSecurityException, PreventedException {        final String username = credential.getUsername();        final String encryptedPassword = this.getPasswordEncoder().encode(credential.getPassword());        try {            final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, username);//          String plain = Encodes.unescapeHtml(credential.getPassword());//          byte[] salt = Digests.generateSalt(SALT_SIZE);//          byte[] hashPassword = Digests.sha1(plain.getBytes(), salt, HASH_INTERATIONS);//          String s=Encodes.encodeHex(salt)+Encodes.encodeHex(hashPassword);//          boolean ss= dbPassword.equals(s);            String plainPassword="123456";            plainPassword=credential.getPassword();            String password="9ec51dc31c730f4b6a719842d1c5a6d2034e653f4fbdafa45ed60104";            password=dbPassword;            String plain1 = Encodes.unescapeHtml(plainPassword);            byte[] salt1 = Encodes.decodeHex(password.substring(0,16));            byte[] hashPassword1 = Digests.sha1(plain1.getBytes(), salt1, HASH_INTERATIONS);            boolean ss1= password.equals(Encodes.encodeHex(salt1)+Encodes.encodeHex(hashPassword1));            if (!ss1) {//            if (!dbPassword.equals(encryptedPassword)) {                throw new FailedLoginException("Password does not match value on record.");            }        } catch (final IncorrectResultSizeDataAccessException e) {            if (e.getActualSize() == 0) {                throw new AccountNotFoundException(username + " not found with SQL query");            } else {                throw new FailedLoginException("Multiple records found for " + username);            }        } catch (final DataAccessException e) {            throw new PreventedException("SQL exception while executing query for " + username, e);        }        return createHandlerResult(credential, new SimplePrincipal(username), null);    }    /**     * @param sql The sql to set.     */    public void setSql(final String sql) {        this.sql = sql;    }}
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78

    修改deployerConfigContext.xml文件

    这里写图片描述

    至此完成Jeesite单点登录集成Cas和自定义登录验证


    jeesite加密研究

    这里写图片描述

    如果直接给密码散列,黑客可以通过查散列值字典(例如MD5密码破解网站),得到某用户的密码。加上salt后就会难上很多,即便是你获得了其中的salt和最终密文,破解也是相当麻烦的。


    盐(Salt),在密码学中,是指通过在密码任意固定位置插入特定的字符串,让散列后的结果和使用原始密码的散列结果不相符,这种过程称之为“加盐”。
    安全因素
    通常情况下,当字段经过散列处理(如MD5),会生成一段散列值,而散列后的值一般是无法通过特定算法得到原始字段的。但是某些情况,比如一个大型的彩虹表,通过在表中搜索该MD5值,很有可能在极短的时间内找到该散列值对应的真实字段内容。

    加盐后的散列值,可以极大的降低由于用户数据被盗而带来的密码泄漏风险,即使通过彩虹表寻找到了散列后的数值所对应的原始内容,但是由于经过了加盐,插入的字符串扰乱了真正的密码,使得获得真实密码的概率大大降低。

    实现原理
    加盐的实现过程通常是在需要散列的字段的特定位置增加特定的字符,打乱原始的字符串,使其生成的散列结果产生变化。比如,用户使用了一个密码:

    x7faqgjw
    经过MD5散列后,可以得出结果:

    455e0e5c2bc109deae749e7ce0cdd397
    但是由于用户密码位数不足,短密码的散列结果很容易被彩虹表破解,因此,在用户的密码末尾添加特定字符串(粗体下划线为加盐的字段):

    x7faqgjwabcdefghijklmnopqrstuvwxyz

    因此,加盐后的密码位数更长了,散列的结果也发生了变化:

    4a1690d5eb6c126ef68606dda68c2f79
    以上就是加盐过程的简单描述,在实际使用过程中,还需要通过特定位数插入、倒序或多种方法对原始密码进行固定的加盐处理,使得散列的结果更加不容易被破解或轻易得到原始密码,比如(绿色字体为加盐字符串):

    这里写图片描述

    其它方式实现单点登录

    使用Cookie解决单点登录 技术点:
    1、设置Cookie的路径为setPath(“/”) .即Tomcat的目录下都有效
    2、设置Cookie的域setDomain(“.gch.com”);即bbs.gch.com,或是mail.gch.com有效。即跨域。
    3、设置Cookie的时间。即使用户不选择在几天内自动登录,也应该保存Cookie以保存在当前浏览器没有关闭的情况下有效。
    4、使用Filter自动登录。

    网上查询到的,未测试,个人觉得可行。

    其他
    `package com.jinfonet.developer.portal;

    import java.io.UnsupportedEncodingException;
    import java.security.MessageDigest;
    import java.security.NoSuchAlgorithmException;

    import javax.validation.constraints.NotNull;

    import org.apache.log4j.chainsaw.Main;
    //import org.inspektr.common.ioc.annotation.NotNull;
    import org.jasig.cas.authentication.handler.PasswordEncoder;
    import org.springframework.util.StringUtils;

    import com.thinkgem.jeesite.common.security.Digests;
    import com.thinkgem.jeesite.common.utils.Encodes;

    import sun.misc.BASE64Encoder;

    /**
    *
    */
    public class JeeSitePasswordEncoder implements PasswordEncoder {

    public static final String HASH_ALGORITHM = "SHA-1";public static final int HASH_INTERATIONS = 1024;public static final int SALT_SIZE = 8;private static final char[] HEX_DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd',        'e', 'f' };@NotNullprivate final String encodingAlgorithm;private String characterEncoding;public JeeSitePasswordEncoder(final String encodingAlgorithm) {    this.encodingAlgorithm = encodingAlgorithm;}public String encode(final String password) {    if (password == null) {        return null;    }    try {        MessageDigest messageDigest = MessageDigest            .getInstance(this.encodingAlgorithm);        if (StringUtils.hasText(this.characterEncoding)) {            messageDigest.update(password.getBytes(this.characterEncoding));        } else {            messageDigest.update(password.getBytes());        }        final byte[] digest = messageDigest.digest();        return getFormattedText(digest);    } catch (final NoSuchAlgorithmException e) {        throw new SecurityException(e);    } catch (final UnsupportedEncodingException e) {        throw new RuntimeException(e);    }} /** * Takes the raw bytes from the digest and formats them correct. * * @param bytes the raw bytes from the digest. * @return the formatted bytes. */private String getFormattedText(final byte[] bytes) {    final StringBuilder buf = new StringBuilder(bytes.length * 2);    for (int j = 0; j < bytes.length; j++) {        buf.append(HEX_DIGITS[(bytes[j] >> 4) & 0x0f]);        buf.append(HEX_DIGITS[bytes[j] & 0x0f]);    }    return buf.toString();}public final void setCharacterEncoding(final String characterEncoding) {    this.characterEncoding = characterEncoding;}/** * 生成安全的密码,生成随机的16位salt并经过1024次 sha-1 hash */public static String entryptPassword(String plainPassword) {    System.out.println("原密码:"+plainPassword);    String plain = Encodes.unescapeHtml(plainPassword);    byte[] salt = Digests.generateSalt(SALT_SIZE);    byte[] hashPassword = Digests.sha1(plain.getBytes(), salt, HASH_INTERATIONS);    String mm=Encodes.encodeHex(salt)+Encodes.encodeHex(hashPassword);    System.out.println("加密后:"+mm);    return mm;}

    /*
    public static void main(String[] args) {
    String s=”1”;
    System.out.println(s);
    System.out.println(entryptPassword(s));
    }*/

    }`

    2
    0
     
     

      相关文章推荐
    • 单点登录之使用eclipse构建cas服务端的war部署包
    • CAS单点登录(三)--服务端改造(登录页及登录方式的自定义)
    • 单点登录(十三)-----实战-----cas4.2.X登录启用mongodb验证方式完整流程
    • 单点登录CAS5-服务端通过数据库认证用户
    • 单点登录(七)-----实战-----cas server去掉https验证
    • 单点登录之cas4.2.7服务端数据库配置(读数据库验证用户并对密码进行加密)
    • 单点登录CAS4-服务端登录页添加验证码
    • 单点登录(十七)----cas4.2.x登录mongodb验证方式成功后返回更多信息更多属性到客户端
    • 单点登录(六)-----遇到问题-----cas server 源码部署导入gradle后有感叹号---错误信息A cycle was detected in the build path of pr
    • 多项目集中权限管理系统 采用cas +shiro+spring mvc+mbatis+bootstrap单点登录