[心缘地方]同学录
首页 | 功能说明 | 站长通知 | 最近更新 | 编码查看转换 | 代码下载 | 常见问题及讨论 | 《深入解析ASP核心技术》 | 王小鸭自动发工资条VBA版
登录系统:用户名: 密码: 如果要讨论问题,请先注册。

[整理]单点登录CAS,在Server端取得客户端IP,get client ip address

上一篇:[备忘]单点登录CAS的超时时间的设置
下一篇:[转帖]CAS 服务器端进入webflow前分析

添加日期:2014/3/5 10:20:04 快速返回   返回列表 阅读4244次
想在用户登录时,不管成功还是失败,写个日志。

别的都好说,就是这个ip,愁死我了。

我是在QueryDatabaseAuthenticationHandler这个类里修改,

它的代码在

cas-server-3.5.2-release.jar的
\cas-server-3.5.2\cas-server-support-jdbc\src\main\java\org\jasig\cas\adaptors\jdbc
下面。

原始内容:


/*
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.jasig.cas.adaptors.jdbc;

import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.springframework.dao.IncorrectResultSizeDataAccessException;

import javax.validation.constraints.NotNull;

/**
 * Class that if provided a query that returns a password (parameter of query
 * must be username) will compare that password to a translated version of the
 * password provided by the user. If they match, then authentication succeeds.
 * Default password translator is plaintext translator.
 * 
 * @author Scott Battaglia
 * @author Dmitriy Kopylenko
 * @version $Revision$ $Date$
 * @since 3.0
 */
public class QueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler {

    @NotNull
    private String sql;

    protected final boolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials) throws AuthenticationException {
        final String username = getPrincipalNameTransformer().transform(credentials.getUsername());
        final String password = credentials.getPassword();
        final String encryptedPassword = this.getPasswordEncoder().encode(
            password);
        
        try {
            final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, username);
            return dbPassword.equals(encryptedPassword);
        } catch (final IncorrectResultSizeDataAccessException e) {
            // this means the username was not found.
            return false;
        }
    }

    /**
     * @param sql The sql to set.
     */
    public void setSql(final String sql) {
        this.sql = sql;
    }
}



可以看到,比较简单,就是执行sql,然后比较密码。

闲言碎语不多讲,直接贴修改后代码:


/*
 * Licensed to Jasig under one or more contributor license
 * agreements. See the NOTICE file distributed with this work
 * for additional information regarding copyright ownership.
 * Jasig licenses this file to you under the Apache License,
 * Version 2.0 (the "License"); you may not use this file
 * except in compliance with the License.  You may obtain a
 * copy of the License at the following location:
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied.  See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.jasig.cas.adaptors.jdbc;

import java.util.Date;

import org.jasig.cas.authentication.handler.AuthenticationException;
import org.jasig.cas.authentication.principal.UsernamePasswordCredentials;
import org.springframework.dao.IncorrectResultSizeDataAccessException;
import org.springframework.web.context.request.RequestContextHolder;

import com.github.inspektr.common.web.ClientInfoHolder;

import javax.validation.constraints.NotNull;

/**
 * Class that if provided a query that returns a password (parameter of query
 * must be username) will compare that password to a translated version of the
 * password provided by the user. If they match, then authentication succeeds.
 * Default password translator is plaintext translator.
 * 
 * @author Scott Battaglia
 * @author Dmitriy Kopylenko
 * @version $Revision$ $Date$
 * @since 3.0
 */
public class QueryDatabaseAuthenticationHandler extends AbstractJdbcUsernamePasswordAuthenticationHandler {

    @NotNull
    private String sql;

    protected final boolean authenticateUsernamePasswordInternal(final UsernamePasswordCredentials credentials) throws AuthenticationException {
        final String username = getPrincipalNameTransformer().transform(credentials.getUsername());
        final String password = credentials.getPassword();
        final String encryptedPassword = this.getPasswordEncoder().encode(
            password);
        
        //插入日志的sql
        String sql = "insert into event_log(event_time,system_name,username,ip,action_type,action_detail,action_result) "+
                "values(?,?,?,?,?,?,?)";
        String ip = ClientInfoHolder.getClientInfo().getClientIpAddress();
        
        try {
            final String dbPassword = getJdbcTemplate().queryForObject(this.sql, String.class, username);
            if(dbPassword.equals(encryptedPassword)){
                //登录成功
                getJdbcTemplate().update(sql, new Object[]{new Date(),"单点登录",username,ip,"登录系统","用户名+密码登录系统","登录成功。"});
                return true;
            }
            
            //密码不正确,登录失败
            getJdbcTemplate().update(sql, new Object[]{new Date(),"单点登录",username,ip,"登录系统","用户名+密码登录系统","登录失败,密码错误。"});
            return false;
        } catch (final IncorrectResultSizeDataAccessException e) {
            RequestContextHolder.getRequestAttributes().getAttribute("aa", 1);
 
            //用户不存在
            getJdbcTemplate().update(sql, new Object[]{new Date(),"单点登录",username,ip,"登录系统","用户名+密码登录系统","登录失败,用户名不存在。"});
            return false;
        }
    }

    /**
     * @param sql The sql to set.
     */
    public void setSql(final String sql) {
        this.sql = sql;
    }
}



IP是这样取得的:
String ip = ClientInfoHolder.getClientInfo().getClientIpAddress();

我去,超级简单哈~~
害我找了N久,搜也搜不到~~

后来看到web.xml中有:


  <filter>
    <filter-name>CAS Client Info Logging Filter</filter-name>
    <filter-class>com.github.inspektr.common.web.ClientInfoThreadLocalFilter</filter-class>
  </filter>
  <filter-mapping>
    <filter-name>CAS Client Info Logging Filter</filter-name>
    <url-pattern>/*</url-pattern>
  </filter-mapping>


看到client info字样,而且之前看过,inspektr好像是个监控意思的类

搜ClientInfoThreadLocalFilter代码,果然有收获:


package com.github.inspektr.common.web;

import java.io.IOException;

import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;

public final class More ...ClientInfoThreadLocalFilter implements Filter {

    public void More ...destroy() {
        // nothing to do here
    }
    
    public void More ...doFilter(final ServletRequest request, final ServletResponse response, final FilterChain filterChain) throws IOException, ServletException {
        try {
            final ClientInfo clientInfo = new ClientInfo((HttpServletRequest) request);
            ClientInfoHolder.setClientInfo(clientInfo);
            filterChain.doFilter(request, response);
        } finally {
            ClientInfoHolder.clear();
        }
    }

    public void More ...init(final FilterConfig filterConfig) throws ServletException {
        // nothing to do
    }
}



它把request对象封成了ClientInfo对象,扔到了ClientInfoHolder里。

以下是ClientInfoHolder的代码 :


package com.github.inspektr.common.web;

public final class ClientInfoHolder {
    
    private static final ThreadLocal<ClientInfo> clientInfoHolder = new ThreadLocal<ClientInfo>();
    
    public static void setClientInfo(final ClientInfo clientInfo) {
        clientInfoHolder.set(clientInfo);
    }
    
    public static ClientInfo getClientInfo() {
        return clientInfoHolder.get();
    }
    
    public static void clear() {
        clientInfoHolder.remove();
    }
}


里面用ThreadLocal来存储clientInfo,
也就是说,每个请求的线程自己保存clientInfo,这样每个人的信息就分开了。

哈哈,好简单,好NB~~

所以咱们在随便哪个类里直接
ClientInfoHolder.getClientInfo()就得到了ClientInfo,

里面就是ClientIP和ServerIP,没别的,呵呵。
 

评论 COMMENTS
没有评论 No Comments.

添加评论 Add new comment.
昵称 Name:
评论内容 Comment:
验证码(不区分大小写)
Validation Code:
(not case sensitive)
看不清?点这里换一张!(Change it here!)
 
评论由管理员查看后才能显示。the comment will be showed after it is checked by admin.
CopyRight © 心缘地方 2005-2999. All Rights Reserved