📄 listener.java
字号:
boolean colonFound = false; StringBuffer userName = new StringBuffer(); StringBuffer password = new StringBuffer(); for( int i = 0; i < decodedString.length; i++ ) { if( (char)decodedString[i] == ':' ) { colonFound = true; continue; } if( (char)decodedString[i] == '\r' || (char)decodedString[i] == '\n' ) continue; if( colonFound ) password.append( (char)decodedString[i] ); else userName.append( (char)decodedString[i] ); } java.net.PasswordAuthentication auth = ( java.net.PasswordAuthentication ) authenticators.get( userName.toString() ); if( ! new String( auth.getPassword() ).equals( password.toString() ) ) throw new APIException( ErrorCode.SERVICE_DENIED, "unauthorized-user", userName ); } else if( authType.equalsIgnoreCase( "digest" ) ) { String digestHeaderValue = authHeader.substring( spaceIndex + 1 ); AuthorizationHeader header = new AuthorizationHeader( digestHeaderValue ); String ourHashValue = computeHash( header ); if( !header.response.equals( ourHashValue ) ) throw new APIException( ErrorCode.SERVICE_DENIED, "unauthorized-user", header.userName ); } else throw new APIException( ErrorCode.CLIENT_ERROR, "unknown-authtype" ); return true; } else { //no auth info supplied, so send him a WWW-Authenticate header drainInputStream( inStream, headers ); sendAuthHeader( outStream ); } return false; } private void sendAuthHeader( OutputStream outStream ) throws IOException, APIException { if( this.authType == RelayConnection.AuthenticationType.BASIC ) { if( logger.isDebugEnabled() ) { NDC.push( "unauthorized" ); logger.debug( "[Begin Outgoing Response To Relay]\n" ); logger.debug( "HTTP/1.1 401 Unauthorized\r\n" + "Connection: Keep-Alive\r\n" + "WWW-Authenticate: Basic realm=\"openwavemm7\"\r\n\r\n" ); logger.debug( "\n[End Outgoing Response To Relay]" ); NDC.pop(); } outStream.write( "HTTP/1.1 401 Unauthorized\r\n".getBytes() ); outStream.write( ( "Connection: Keep-Alive\r\n" ).getBytes() ); outStream.write( ( "WWW-Authenticate: Basic realm=\"openwavemm7\"\r\n\r\n" ).getBytes() ); outStream.flush(); } else { String nonce = genNonce(); if( logger.isDebugEnabled() ) { NDC.push( "unauthorized" ); logger.debug( "[Begin Outgoing Response To Relay]\n" ); logger.debug( "HTTP/1.1 401 Unauthorized\r\n" + "Connection: close\r\n" + "WWW-Authenticate: Digest realm=\"openwavemm7\"," + "algorithm=\"MD5\",qop=\"auth\",nonce=\"" + nonce + "\"\r\n\r\n" ); logger.debug( "\n[End Outgoing Response To Relay]" ); NDC.pop(); } outStream.write( "HTTP/1.1 401 Unauthorized\r\n".getBytes() ); outStream.write( ( "Connection: Keep-Alive\r\n" ).getBytes() ); outStream.write( ( "WWW-Authenticate: Digest realm=\"openwavemm7\"," + "algorithm=\"MD5\",qop=\"auth\",nonce=\"" + nonce + "\"\r\n\r\n" ).getBytes() ); outStream.flush(); } } // Base64(Time)+SHA(Secret+realm+time) private String genNonce() throws APIException { Long now = new Long( System.currentTimeMillis() ); String timeBase64 = new String( Base64.encodeString( now.toString() )).trim(); MessageDigest digest = null; try { digest = MessageDigest.getInstance( "SHA" ); } catch( NoSuchAlgorithmException nsae ) { throw new APIException( ErrorCode.SERVER_ERROR, "no-sha" ); } digest.update( secret ); digest.update( "openwavemm7".getBytes() ); digest.update( timeBase64.getBytes() ); byte[] baDigest = digest.digest(); return timeBase64 + convertDigestToString( baDigest ); } class AuthorizationHeader { public String userName; public String realm; public String response; public String nonce; public String uri; public String nonceCount; public String cNonce; public String qop; public AuthorizationHeader( String authHeaderValue ) throws APIException { StringTokenizer parser = new StringTokenizer( authHeaderValue, ", " ); String token = null; while( parser.hasMoreTokens() ) { token = parser.nextToken( ); int equalsIndex = token.indexOf( '=' ); if( equalsIndex == -1 ) throw new APIException( ErrorCode.CLIENT_ERROR, "bad-authorization-header" ); String key = token.substring( 0, equalsIndex ).toLowerCase(); String value = token.substring( equalsIndex + 2 , token.length() - 1 ); if( key.equals( "realm" ) ) { realm = value; } else if( key.equals( "response" ) ) { response = value; } else if( key.equals( "nonce" ) ) { nonce = value; } else if( key.equals( "qop" ) ) { qop = value; } else if( key.equals( "username" ) ) { userName = value; } else if( key.equals( "cnonce" ) ) { cNonce = value; } else if( key.equals( "uri" ) ) { uri = value; } else if( key.equals( "nc" ) ) { nonceCount = value; } } } } private String computeHash( AuthorizationHeader header ) throws APIException { java.net.PasswordAuthentication auth = ( java.net.PasswordAuthentication ) authenticators.get( header.userName ); if( auth == null ) throw new APIException( "unauthorized-user", header.userName ); MessageDigest digest = null; try { digest = MessageDigest.getInstance( "MD5" ); } catch( NoSuchAlgorithmException nsae ) { throw new APIException( ErrorCode.SERVER_ERROR, "no-md5" ); } String ha1 = convertDigestToString( digest.digest( ( header.userName + ":" + header.realm + ":" + new String( auth.getPassword() ) ) .getBytes() ) ); digest.reset(); String ha2 = convertDigestToString( digest.digest( ( "POST:" + header.uri ).getBytes() )); digest.reset(); String response = convertDigestToString( digest.digest( ( ha1 + ":" + header.nonce + ":" + header.nonceCount + ":" + header.cNonce + ":" + header.qop + ":" + ha2 ).getBytes() ) ); return response; } private String convertDigestToString( byte[] digest ) { // md5 digests are always 16 bytes. this function divides each byte // into two and converts them to hex chars StringBuffer buf = new StringBuffer( 32 ); for( int i = 0; i < 16; i++ ) { String hex = Integer.toHexString( digest[i] ); if( hex.length() > 2 ) hex = hex.substring( 6 ); if( hex.length() < 2 ) hex = "0" + hex; buf.append( hex ); } return buf.toString(); } private void drainInputStream( InputStream inStream, InternetHeaders headers ) throws IOException, APIException { String[] contentLength = headers.getHeader( "content-length" ); if( contentLength == null || contentLength[0].length() == 0 ) inStream.skip( inStream.available() ); else { try { inStream.skip( Integer.parseInt( contentLength[0] ) ); } catch( NumberFormatException nfe ) { throw new APIException( "content length header value NAN" ); } } } private void writeResponse( Response res, OutputStream outputStream ) throws IOException, SOAPException { writeHeaders( outputStream ); if( res != null ) res.writeTo( outputStream ); if( logger.isDebugEnabled() ) { logger.debug( "[End Outgoing Response To Relay]" ); } } private static final Logger logger = Logger.getLogger( Listener.class ); private ServerSocket server; private HashMap authenticators; private byte[] secret; private RelayConnection.AuthenticationType authType; private RelayConnection relayConn;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -