精华内容
下载资源
问答
  • jquery密码强度校验

    2020-10-23 05:45:46
    主要介绍了jquery密码强度校验,这是一个非常常见的功能,在输入密码的时候提示密码的强度,本文使用jQuery来实现,需要的小伙伴可以参考下。
  • 登录校验码综述

    2017-11-09 12:34:39
    常见的几类验证码主要有: (1)根据图片中给出的数字、字母、汉字,输入相应内容 (2)拖动部分图形完成拼图 (3)根据给出提示信息,选择相应的图片或者按顺序选择汉字 (4)智能无校验型 提供验证码服务...

    最近在查找有关登录界面验证码相关技术,下面根据自己的搜索结果加以简单的概括归纳:

    常见的几类验证码主要有:

    (1)根据图片中给出的数字、字母、汉字,输入相应内容

    (2)拖动部分图形完成拼图

    (3)根据给出提示信息,选择相应的图片或者按顺序选择汉字

    (4)智能无校验型


    提供验证码服务的主要厂商:阿里云、网易、腾讯、极验、点触、luosimao(螺丝帽)等

    展开全文
  • socket是一个常见的网络协议。这篇文章我们用一个简单的聊天室的例子,来实践一下TCP和UDP在socket中的应用。 案例一:UDP聊天室 这个案例中,两个主要的类 DatagramSocket:代表UDP协议的Socket,DatagramSocket...

    Socket通信与Https通信

    本项目demo:DEMO
    下载麻烦点下小星星,谢谢!

    Part1- Socket通信

    socket是一个常见的网络协议。这篇文章我们通4过个简单的聊天室的例子,来实践一下TCP和UDP在socket中的应用。以及使用Https协议的时候,我们客户端所需要的操作。

    在一切开始之前,需要在mainfest.xml文件中申请网络使用权限
    .
    .
    .

    案例一:UDP聊天室

    这个案例中,有两个主要的类

    • DatagramSocket:代表UDP协议的Socket,DatagramSocket本身只是码头,不维护状态,不能产生IO流,它的唯一作用就是接收和发送数据报。
    • DatagramPacket:代表数据报文,UDP传输过程中数据的载体

    具体的细节在代码的备注中,代码主要分为客户端和服务器端,模拟进行通讯。

    UDP服务器端代码:

    package com.example.chatroom.udp;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    import java.util.Scanner;
    
    public class UdpServer {
    
        private InetAddress mAddress;//指定IP地址
        private int mPort = 7777; //用于指定监听的端口号
        private DatagramSocket mSocket;
    
        private Scanner scanner;
    
    
        public static void main(String[] args) {
            System.out.println("server is started!");
            new UdpServer().start();
        }
    
        public UdpServer()
        {
            try {
                mAddress = InetAddress.getLocalHost();//获取本机InetAddress实例
                mSocket = new DatagramSocket(mPort,mAddress);//构造DatagramSocket对象
                scanner = new Scanner(System.in);//获取输入
                scanner.useDelimiter("\n");
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (SocketException e) {
                e.printStackTrace();
            }
    
        }
    
    
        public void start() {
            while (true) {
                byte[] bytes = new byte[1024];
                DatagramPacket receivePacket = new DatagramPacket(bytes, bytes.length);//载体
                try {
                    mSocket.receive(receivePacket);//收取服务器发来的信息
    
                    InetAddress address = receivePacket.getAddress();//获取报文中的ip地址
                    int port = receivePacket.getPort();//获取端口号
                    byte[] data = receivePacket.getData();//获取报文中的数据
                    String clientMessage = new String(data, 0, receivePacket.getLength());//用bute数组构建String对象
    
                    System.out.println("address:" + address + "," + "port:" + port + "," + "clientMessage:" + clientMessage);
    
                    String returnedMessage = scanner.next();//获取控制台的输入
                    byte[] reruened = returnedMessage.getBytes();//转换为byte数组
    
                    DatagramPacket sentPacket = new DatagramPacket(reruened, reruened.length, receivePacket.getSocketAddress());//构建成数据包包
                    mSocket.send(sentPacket);//发送数据报
    
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    
    }
    
    

    UDP客户端代码:

    package com.example.chatroom.udp;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    import java.util.Scanner;
    
    public class UdpClient {
    
        private String mServerIp = "192.168.3.8";//指定要访问服务的IP
        private InetAddress mInetAddress;
        private int mServerPort = 7777;//要访问的端口号
        private DatagramSocket mSocket;
        private Scanner mScanner;
    
        public static void main(String[] args) {
            System.out.println("client is started!");
            new UdpClient().start();
        }
    
        public UdpClient()
        {
            try {
                mSocket = new DatagramSocket();
                mInetAddress = InetAddress.getByName(mServerIp);//构造InetAddress 对象
                mScanner = new Scanner(System.in);
                mScanner.useDelimiter("\n");
            } catch (SocketException e) {
                e.printStackTrace();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
    
        public void start()
        {
            while (true){
                try {
                String clientMessage = mScanner.next();//获取控制台输入的数据
    
                byte[] clientMessageBytes = clientMessage.getBytes();
    
                DatagramPacket clientPacket = new DatagramPacket(clientMessageBytes,
                        clientMessageBytes.length,mInetAddress,mServerPort);//将数据打包到DatagramPacket 中
    
                    mSocket.send(clientPacket);//通过socket发送数据
    
    
                    byte[] bytes = new byte[1024];
                    DatagramPacket serverMsgPacket = new DatagramPacket(bytes,bytes.length);
                    mSocket.receive(serverMsgPacket);//接收服务器发来的数据
    
    
    
    //                InetAddress address = serverMsgPacket.getAddress();
    //                int port = serverMsgPacket.getPort();
                    byte[] data = serverMsgPacket.getData();
                    String serverMessage = new String(data, 0, serverMsgPacket.getLength());
    
                    System.out.println( "serverMessage:" + serverMessage);//将数据打印在控制台
    
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }
    
    

    测试结果如下:

    在这里插入图片描述
    在这里插入图片描述
    值得注意的是, mSocket.receive()方法在没有收到数据的时候会一直处于阻塞状态。

    我们可以以将客户端的代码迁移到安卓上,布局如下:

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        xmlns:app="http://schemas.android.com/apk/res-auto"
        xmlns:tools="http://schemas.android.com/tools"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".UDPActivity">
        <LinearLayout
            android:orientation="horizontal"
            android:layout_width="match_parent"
            android:layout_height="50dp">
    
    
        <EditText
            android:id="@+id/input"
            android:layout_width="0dp"
            android:layout_weight="3"
            android:layout_height="wrap_content"
            android:text="Hello World!" />
            <Button
                android:id="@+id/send"
                android:text="发送"
                android:layout_width="0dp"
                android:layout_weight="1"
                android:layout_height="match_parent"/>
        </LinearLayout>
        <ScrollView
            android:layout_marginTop="50dp"
            android:layout_width="match_parent"
            android:layout_height="match_parent">
    
            <TextView
                android:id="@+id/message"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"/>
    
    
        </ScrollView>
    
    </RelativeLayout>
    

    就是这个样子的:
    在这里插入图片描述
    迁移之后,安卓端代码如下:
    首先我们将消息发送的业务逻辑迁移到一个新的类中,代码和之前客户端的基本一致:

    package com.example.chatroom.biz;
    
    import android.os.Handler;
    import android.os.Looper;
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import java.net.SocketException;
    import java.net.UnknownHostException;
    
    public class UdpClientBiz {
    
        private String mServerIp = "192.168.2.101";
        private InetAddress mInetAddress;
        private int mServerPort = 7777;
        private DatagramSocket mSocket;
    
        private Handler mUIHandler = new Handler(Looper.getMainLooper());//将handler声明在主线程中,方便我们操作UI
    
    //创建一个接口在进行收到消息和发生异常时候的回调
        public interface OnMessageReturnListener
        {
            void onMessageReturn(String message);
            void onError(Exception e);
    
        }
    
        public void sendMsg(final String msg, final OnMessageReturnListener onMessageReturnListener)
        {
            new Thread(){
                @Override
                public void run() {
                    try {
                        //sendmessage
                        byte[] clientMessageBytes = msg.getBytes();
    
                        DatagramPacket clientPacket = new DatagramPacket(clientMessageBytes,
                                clientMessageBytes.length,mInetAddress,mServerPort);
                        mSocket.send(clientPacket);
    
                        //reciveMessage
                        byte[] bytes = new byte[1024];
                        DatagramPacket serverMsgPacket = new DatagramPacket(bytes,bytes.length);
                        mSocket.receive(serverMsgPacket);
                        final String serverMessage = new String(serverMsgPacket.getData(), 0, serverMsgPacket.getLength());
    
                        mUIHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                onMessageReturnListener.onMessageReturn(serverMessage);
                            }
                        });
    
    
                        System.out.println( "clientMessage:" + serverMessage);
                    } catch (final IOException e) {
                        e.printStackTrace();
                        mUIHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                onMessageReturnListener.onError(e);
                            }
                        });
    
                    }
                }
            }.start();
    
        }
    
        public UdpClientBiz()
        {
            try {
                mSocket = new DatagramSocket();
                mInetAddress = InetAddress.getByName(mServerIp);
            } catch (SocketException e) {
                e.printStackTrace();
            } catch (UnknownHostException e) {
                e.printStackTrace();
            }
        }
    
    
        public void destory()
        {
            if (mSocket != null)
            {
                mSocket.close();
            }
        }
    
    }
    
    

    在Activity中:

    package com.example.chatroom;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.os.Bundle;
    import android.text.TextUtils;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    
    import com.example.chatroom.biz.UdpClientBiz;
    
    public class UDPActivity extends AppCompatActivity  {
        private EditText mEditText;
        private Button mButtonSend;
        private TextView mTextViewMessage;
    
        private UdpClientBiz udpClientBiz = new UdpClientBiz();
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
            setTitle("UDP_CHATROOM");
    
            initView();
    
            mButtonSend.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
    
                    String messages = mEditText.getText().toString();
                    if (TextUtils.isEmpty(messages))
                    {
                        return;
                    }
                    appendMessage2Content("client:"+messages);
                    udpClientBiz.sendMsg(messages, new UdpClientBiz.OnMessageReturnListener() {
                        @Override
                        public void onMessageReturn(String message) {
                            appendMessage2Content("server:"+message);
                        }
    
                        @Override
                        public void onError(Exception e) {
                            e.printStackTrace();
                        }
                    });
                    mEditText.setText(" ");
    
                }
            });
        }
    
        private void appendMessage2Content(String message) {
            mTextViewMessage.append(message+"\n");
        }
    
        private void initView() {
            mEditText = findViewById(R.id.input);
            mButtonSend = findViewById(R.id.send);
            mTextViewMessage = findViewById(R.id.message);
        }
    
    
    }
    
    
    

    结果如下:
    在这里插入图片描述

    案例二:TCP聊天室

    相比UDP而言,TCP就显得比较简洁。我们只需要通过ServerSocket的输入流/输出流来获取客户端/服务器发来的数据。
    虽然比较简洁,但我们的这个例子却不太简单。这个案例实现的是多个客户端和服务器组成的多人聊天室。由于聊天室不是1对1的,所以需要一个消息缓存的机制,然后让服务器循环从消息池中取出消息,转发到客户端。

    我们先看消息池是怎么样的:

    package com.example.chatroom.tcp.server;
    
    import java.util.ArrayList;
    import java.util.List;
    import java.util.concurrent.LinkedBlockingQueue;
    
    public class MessagePool {
    
        private static MessagePool messagePoolInstance = new MessagePool();//单例
        private LinkedBlockingQueue<String> messageQueue = new LinkedBlockingQueue();//消息队列
        private List<MessageConmingListener> msgListeners = new ArrayList<>();
    
    
        public MessagePool() {
        }
    
    
    
    //获取单例,为例简单先不做锁
        public static MessagePool getMessagePoolInstance()
        {
            return messagePoolInstance;
        }
    
    //发送消息的方法
        public void sendMessage(String message)
        {
            try {
                messageQueue.put(message);//将消息放入消息队列
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    
        public void start()
        {
            new Thread(){
                @Override
                public void run() {
                    while (true){
                        try {
                            String msg = messageQueue.take();//从消息队列中取出消息
                            notifiMessageComing(msg);//使用观察者模式,通知客户端新消息
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
    
                    }
                }
            }.start();
        }
    
    //通知客户端新的消息
        private void notifiMessageComing(String msg) {
            for (MessageConmingListener listener:msgListeners) {
                listener.onMessageComing(msg);
            }
        }
    
    //消息监听器接口
        public interface MessageConmingListener
        {
            void onMessageComing(String message);
        }
    
    //注册消息监听器
        public void addMessageConmingListener(MessageConmingListener messageConmingListener)
        {
            msgListeners.add(messageConmingListener);
        }
    }
    
    

    然后我们看服务器端:

    package com.example.chatroom.tcp.server;
    
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.net.Socket;
    
    public class TCPServer {
    
        public void start() {
            ServerSocket serverSocket = null;
            try {
                serverSocket = new ServerSocket(9090);//监听9090端口
                MessagePool.getMessagePoolInstance().start();//开始从消息池中取出消息,并发出去
                while (true) {
                    Socket socket = serverSocket.accept();//接收客户端的请求,并拿到存储了客户端数据的Socket对象
                    System.out.println("ip:" + socket.getInetAddress().getHostAddress()
                            + ", port:" + socket.getPort() + "is online now ...");
    
                    ClientTask clientTask = new ClientTask(socket);//给这个socket所代表的客户端注册一个ClientTask 
                    MessagePool.getMessagePoolInstance().addMessageConmingListener(clientTask);//将ClientTask 加入到观察者中
                    clientTask.start();
    
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            new TCPServer().start();
        }
    }
    
    

    我们看看clientTask:

    package com.example.chatroom.tcp.server;
    
    import java.io.BufferedReader;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.net.Socket;
    
    //实现了消息监听的接口,继承自Thread类
    public class ClientTask extends Thread implements MessagePool.MessageConmingListener {
    
        private Socket mSocket;
        private InputStream inputStream;
        private OutputStream outputStream;
    
        public ClientTask(Socket Socket) {
    
            try {
                mSocket = Socket;
                inputStream = mSocket.getInputStream();
                outputStream = mSocket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
        @Override
        public void run() {
            BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));//用BufferReader从输入流中读取数据
            try {
                String line ;
    
                while ((line = br.readLine())!=null)
                {
                    System.out.println("read:"+line);
                    //转发消息给其他客户端
                    MessagePool.getMessagePoolInstance().sendMessage("port:"+mSocket.getPort()+"  message:"+line);
    
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    
    //在消息池中被回调
        @Override
        public void onMessageComing(String message) {
            try {
            //向连接到服务的客户端写数据
                outputStream.write(message.getBytes());
                outputStream.write("\n".getBytes());
                outputStream.flush();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
    
    

    最后我们看一下客户端类:

    package com.example.chatroom.tcp.client;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    import java.util.Scanner;
    
    public class TCPClient {
    
    
        private Scanner mScanner;
    
        public TCPClient() {
            this.mScanner = new Scanner(System.in);
            mScanner.useDelimiter("\n");
        }
    
        public void start()
        {
            try {
                Socket socket = new Socket("192.168.2.100",9090);//访问对应ip下的端口
                InputStream inputStream = socket.getInputStream();
                OutputStream outputStream = socket.getOutputStream();
    
                final BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
                BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));
    
                new Thread(){
                    @Override
                    public void run() {
                        String line = null;
                        try {
    
                            while ((line = br.readLine()) != null) {
    
                                System.out.println(line);//将受到的消息打印到控制台
                            }
                        }
                        catch (Exception e)
                        {
                            e.printStackTrace();
                        }
                    }
                }.start();
    
    
                while (true)
                {
                //将控制台输入的消息发送到服务器
                    String msg =  mScanner.next();
                    bw.write(msg);
                    bw.newLine();
                    bw.flush();
    
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    
        public static void main(String[] args) {
            new TCPClient().start();
        }
    }
    
    

    效果如下:
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述
    我们可以在对应的socket做一些标识,例如昵称什么的,然后就可以得到和真正的聊天类似的效果。

    然后我们将这个功能迁移带客户端:
    我们新建一个业务类,将客户端中带部分代码分割出去:

    package com.example.chatroom.biz;
    
    import android.os.Handler;
    import android.os.Looper;
    
    import java.io.BufferedReader;
    import java.io.BufferedWriter;
    import java.io.IOException;
    import java.io.InputStream;
    import java.io.InputStreamReader;
    import java.io.OutputStream;
    import java.io.OutputStreamWriter;
    import java.net.Socket;
    
    public class TCPClientBiz {
        private Socket socket ;
        private InputStream inputStream ;
        private OutputStream outputStream ;
    
        private Handler mUIHandler = new Handler(Looper.getMainLooper());
    
    
        private  OnMsgReceiveListener mListener;
    
        public void setOnMsgReceiveListener(OnMsgReceiveListener onMsgReceiveListener) {
            mListener = onMsgReceiveListener;
        }
    
        public TCPClientBiz() {
    
            new Thread() {
                @Override
                public void run() {
                    try {
                        socket= new Socket("192.168.2.101",9090);
                        inputStream = socket.getInputStream();
                        outputStream = socket.getOutputStream();
    
                        readServerMsg();
                    }
                    catch (final Exception e)
                    {
                        mUIHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                if (mListener !=null) {
                                    mListener.onError(e);
                                }
                            }
                        });
                        e.printStackTrace();
                    }
                }
            }.start();
    
        }
    
        public void sendMessage(final String msg ) {
            new Thread() {
                @Override
                public void run() {
                    try {
                        BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(outputStream));
                        bw.write(msg);
                        bw.newLine();
                        bw.flush();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }.start();
        }
    
        private void readServerMsg() throws IOException {
             BufferedReader br = new BufferedReader(new InputStreamReader(inputStream));
            String line = null;
            while ((line = br.readLine()) != null) {
                final String finalLine = line;
                mUIHandler.post(new Runnable() {
                    @Override
                    public void run() {
                        if (mListener !=null) {
                            mListener.onMessageReceived(finalLine);
                        }
                    }
                });
    
            }
        }
    
        public interface OnMsgReceiveListener
        {
            void onMessageReceived(String msg);
            void onError(Exception e);
        }
    
        public void onDestory()
        {
    
            try {
                if (socket!=null)
                {
                    socket.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (inputStream !=null)
                {
                    inputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
            try {
                if (outputStream != null)
                {
                    outputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
    
        }
    
    }
    
    

    然后是Activity的代码:

    package com.example.client;
    
    
    import android.os.Bundle;
    import android.text.TextUtils;
    import android.view.View;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.TextView;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import com.example.chatroom.biz.TCPClientBiz;
    
    public class TCPActivity extends AppCompatActivity  {
        private EditText mEditText;
        private Button mButtonSend;
        private TextView mTextViewMessage;
    
        private TCPClientBiz tcpClientbiz;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_t_c_p);
            tcpClientbiz = new TCPClientBiz();
            tcpClientbiz.setOnMsgReceiveListener(new TCPClientBiz.OnMsgReceiveListener() {
                @Override
                public void onMessageReceived(String msg) {
                    appendMessage2Content(msg);//将受到的消息放在textview中
                }
    
                @Override
                public void onError(Exception e) {
    
                }
            });
    
            initView();
    
            mButtonSend.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View v) {
                    mTextViewMessage.setText(" ");
                    String messages = mEditText.getText().toString();
                    if (TextUtils.isEmpty(messages))
                    {
                        return;
                    }
                    appendMessage2Content("client:"+messages);
                    tcpClientbiz.sendMessage(messages);
    
                }
            });
        }
    
        private void appendMessage2Content(String message) {
            mTextViewMessage.append(message+"\n");
        }
    
        private void initView() {
            mEditText = findViewById(R.id.input);
            mButtonSend = findViewById(R.id.send);
            mTextViewMessage = findViewById(R.id.message);
        }
    
        @Override
        protected void onDestroy() {
            super.onDestroy();
            tcpClientbiz.onDestory();
        }
    }
    
    

    在这里插入图片描述
    这里需要注意的是,要将客户端的代码放在另外一个module 中,不然会运行不起来。

    Part2-Https通信

    Https是是一种采用了加密算法的通讯协议。为了安全起见,在安卓端访问使用了Https协议的服务的时候(服务并未获得CA证书)需要校验证书以及域名,来保证数据的安全性。

    案例三:证书校验以及域名校验
    我们先写一个Utils来访问一个链接:

    package https;
    
    import android.content.Context;
    import android.os.Handler;
    import android.os.Looper;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import java.net.URL;
    import java.security.KeyManagementException;
    import java.security.KeyStore;
    import java.security.KeyStoreException;
    import java.security.NoSuchAlgorithmException;
    import java.security.SecureRandom;
    import java.security.cert.Certificate;
    import java.security.cert.CertificateException;
    import java.security.cert.CertificateFactory;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.HostnameVerifier;
    import javax.net.ssl.HttpsURLConnection;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSession;
    import javax.net.ssl.TrustManager;
    import javax.net.ssl.TrustManagerFactory;
    
    public class HttpUtils {
    
        private static Handler mUIHandler = new Handler(Looper.getMainLooper());
        public interface HttpListener
        {
            void onSucceed(String content);
            void onFailed(Exception e);
        }
    
        public static void doGet(final Context context,final String urlStr, final HttpListener httpListener)
        {
            new Thread()
            {
                @Override
                public void run() {
    
                    InputStream inputStream = null;
                    try {
                        URL url = new URL(urlStr);
                        HttpsURLConnection httpConn = (HttpsURLConnection) url.openConnection();
    
    
    
                        //校验证书_方法1:
                        X509Certificate certificate = getCert(context);
                        TrustManager[] tm = {new MyX509TrustManager(certificate)};
                        SSLContext sslContext = SSLContext.getInstance("TLS");
                       
    
                        //校验证书_方法2:
                        String keyStoreType = KeyStore.getDefaultType();
                        KeyStore keyStore = KeyStore.getInstance(keyStoreType);
                        keyStore.load(null);
                        keyStore.setCertificateEntry("srca",certificate);
    
                        TrustManagerFactory trustManagerFactory
                                = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
    
                        trustManagerFactory.init(keyStore);
    
                        TrustManager[] tm1 = trustManagerFactory.getTrustManagers();
    
    
    //在获取了TrustManager[]数组之后的步骤就相同了
    
                        sslContext.init(null,tm,new SecureRandom());
                        httpConn.setSSLSocketFactory(sslContext.getSocketFactory());
    
                        //校验域名
                        httpConn.setHostnameVerifier(new HostnameVerifier() {
                            @Override
                            public boolean verify(String hostname, SSLSession session) {
    
                                HostnameVerifier defaultHostnameVerifier = HttpsURLConnection.getDefaultHostnameVerifier();
                                return defaultHostnameVerifier.verify("12306.cn",session);
    
    
    
                            }
                        });
    
    
                        httpConn.setDoInput(true);
                        httpConn.setDoOutput(true);
                        httpConn.setRequestMethod("GET");
                        httpConn.setConnectTimeout(5*1000);
                        httpConn.setReadTimeout(5*1000);
                        httpConn.connect();
    
                        final StringBuilder content = new StringBuilder();
                        inputStream = httpConn.getInputStream();
                        byte[] buf  = new byte[2048];
                        int len = -1;
                        while ((len = inputStream.read(buf))!=-1)
                        {
                            content.append(new String(buf,0,len));
                        }
                        mUIHandler.post(new Runnable() {
                            @Override
                            public void run() {
                                httpListener.onSucceed(content.toString());
                            }
                        });
    
                    } catch (MalformedURLException e) {
                        e.printStackTrace();
                        httpListener.onFailed(e);
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (NoSuchAlgorithmException e) {
                        e.printStackTrace();
                    } catch (KeyManagementException e) {
                        e.printStackTrace();
                    } catch (KeyStoreException e) {
                        e.printStackTrace();
                    } catch (CertificateException e) {
                        e.printStackTrace();
                    } finally {
                        if (inputStream!=null)
                        {
                            try {
                                inputStream.close();
                            } catch (IOException e) {
                                e.printStackTrace();
                            }
                        }
                    }
                }
            }.start();
    
        }
    
        private static X509Certificate getCert(Context context) {
    
            try {
                InputStream inputStream = context.getAssets().open("xxx.cer");//在本地assets目录下保存的网站证书
                CertificateFactory certificateFactory = CertificateFactory.getInstance("X509");
                 return (X509Certificate) certificateFactory.generateCertificate(inputStream);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (CertificateException e) {
                e.printStackTrace();
            }
            return null;
        }
    }
    
    
    

    其中,MyX509TrustManager类为:

    package https;
    
    import java.security.cert.CertificateException;
    import java.security.cert.X509Certificate;
    
    import javax.net.ssl.X509TrustManager;
    
    public class MyX509TrustManager implements X509TrustManager {
    
        private X509Certificate mySeverCert;
    
        public MyX509TrustManager(X509Certificate mySeverCert) {
            this.mySeverCert = mySeverCert;
        }
    
        @Override
        public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException {
    
        }
    
        @Override
        public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException {
            for (X509Certificate certificate : chain)
            {
                //证书是否过期以及合法性校验
                certificate.checkValidity();
    
                try {
                    certificate.verify(mySeverCert.getPublicKey());
                } catch (Exception e) {
                //出现错误代表证书验证失败
                   throw new CertificateException(e);
                }
            }
    
        }
    
        @Override
        public X509Certificate[] getAcceptedIssuers() {
            return new X509Certificate[0];
        }
    }
    
    

    证书校验的两种方法,第一种需要我们自己去校验,第二种是调用API为我们校验。

    展开全文
  • 商品条码类型常见的是13位商品条码(目前主要是EAN-13和EAN-8)是国际组织公布的非强制标准,是一类一码。商品条码的特点是最后一位为校验码,根据前面的条码数据校验自动生成。 商品条码的另一个特性是附加码,而...

    商品条码类型常见的是13位商品条码(目前主要是EAN-13和EAN-8)是国际组织公布的非强制标准,是一类一码。商品条码的特点是最后一位为校验码,根据前面的条码数据校验自动生成。
    商品条码的另一个特性是有附加码,而我们常见到的是不显示这个附加码的。如图:
    在这里插入图片描述
    含附加码的商品条码该如何制作呢?
    1、启动Label mx条码打印软件,使用条码工具在页面中画出一个一维码,这里默认是条码类型就是EAN-13。在字符框里输入12位条码数据,软件会自动生成含校验码的完整条形码及数据。
    在这里插入图片描述
    2、在属性栏中,勾选附加码前面的方框,点击附加码图标。在弹出的选择框里可以看到附加码的三种不同样式。下图为软件做出的三种样式。
    在这里插入图片描述
    3、在附加码设置窗口里还可以看到“附加码长度”选项,默认长度是2,点开后还有一个选择是5。中间条码为附加码长度为5的效果。
    在这里插入图片描述
    4、国际通用的商品条码类型是UPC-A和UPC-E。他们也有附加码属性。属性设置跟EAN-13一样。
    在这里插入图片描述
    5、采用上述属性及操作步骤,UPC-A和UPC-E各种形式的附加码样式如下。
    在这里插入图片描述

    展开全文
  • Shiro 是一个强大、简单易用 Java 安全框架,主要用来更便捷认证,授权,加密,会话管理等,可为任何应用提供安全保障,今天主要介绍 Shiro 认证和授权功能。 三大核心组件 Subject :认证主体。它包含两个...

    Shiro说明

    Shiro 是一个强大、简单易用的 Java 安全框架,主要用来更便捷的认证,授权,加密,会话管理等,可为任何应用提供安全保障,今天主要介绍 Shiro 的认证和授权功能。


    三大核心组件

    • Subject :认证主体。它包含两个信息:PrincipalsCredentials
          Principals:身份。可以是用户名,邮件,手机号码等等,用来标识一个登录主体身份
          Credentials:凭证。常见有密码,数字证书等等
    • SecurityManager :安全管理员,是Shiro架构的核心
    • Realm:Realms 是一个域,它是连接Shiro和具体应用的桥梁

    集成Shiro过程

    1. 引入依赖
    	<dependencies>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>com.github.ulisesbocchio</groupId>
                <artifactId>jasypt-spring-boot-starter</artifactId>
                <version>2.1.1</version>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid-spring-boot-starter</artifactId>
                <version>1.1.10</version>
            </dependency>
            <dependency>
                <groupId>org.mybatis.spring.boot</groupId>
                <artifactId>mybatis-spring-boot-starter</artifactId>
                <version>2.1.2</version>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
                <version>6.0.6</version>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.17</version>
            </dependency>
            <dependency>
                <groupId>org.projectlombok</groupId>
                <artifactId>lombok</artifactId>
                <optional>true</optional>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-redis</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-cache</artifactId>
            </dependency>
            <dependency>
                <groupId>org.apache.commons</groupId>
                <artifactId>commons-pool2</artifactId>
                <version>2.0</version>
            </dependency>
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>spring-context-support</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-freemarker</artifactId>
            </dependency>
            <dependency>
                <groupId>org.apache.shiro</groupId>
                <artifactId>shiro-spring</artifactId>
                <version>1.4.0</version>
            </dependency>
        </dependencies>
    
    1. 建立权限数据库表
      这里我们给出表结构,大家可以自行设计
    ##权限表
    CREATE TABLE `hotel_permission` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `parentId` int(11) DEFAULT NULL,
      `permissName` varchar(50) DEFAULT NULL,
      `permissNice` varchar(50) DEFAULT NULL,
      `permissType` varchar(2) DEFAULT NULL,
      `permissUri` varchar(50) DEFAULT NULL,
      `crtUserId` int(11) DEFAULT NULL,
      `crtTime` datetime DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
    ##角色表
    CREATE TABLE `hotel_role` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `roleName` varchar(50) DEFAULT NULL,
      `description` varchar(100) DEFAULT NULL,
      `crtUserId` int(20) DEFAULT NULL,
      `crtTime` datetime DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    ##用户表
    CREATE TABLE `hotel_user` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `username` varchar(50) DEFAULT NULL,
      `password` varchar(100) DEFAULT NULL,
      `phone` varchar(20) DEFAULT NULL,
      `sex` varchar(2) DEFAULT NULL,
      `age` varchar(3) DEFAULT NULL,
      `address` varchar(100) DEFAULT NULL,
      `crtUserId` int(20) NOT NULL,
      `crtTime` datetime DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8;
    ##角色权限关联表
    CREATE TABLE `hotel_role_permiss` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `roleId` int(11) DEFAULT NULL,
      `permissId` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;
    ##用户角色关联表
    CREATE TABLE `hotel_user_role` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `userId` int(11) DEFAULT NULL,
      `roleId` int(11) DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB AUTO_INCREMENT=3 DEFAULT CHARSET=utf8;
    

    3)自定义Realm
    有了数据库表和数据之后,我们开始自定义 realm,自定义 realm 需要继承 AuthorizingRealm 类,因
    为该类封装了很多方法,它也是一步步继承自 Realm 类的,继承了 AuthorizingRealm 类后,需要重写
    两个方法

    doGetAuthenticationInfo() 方法:用来验证当前登录的用户,获取认证信息
    doGetAuthorizationInfo() 方法:用来为当前登陆成功的用户授予权限和角色

    public class RealmShiro extends AuthorizingRealm {
    
        @Autowired
        private IHotelPermissionService permissionService;
        @Autowired
        private IHotelRoleService roleService;
        @Autowired
        private IHotelUserService userService;
    
        @Override
        protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principal) {
            HotelUser user = (HotelUser) principal.getPrimaryPrincipal();
            Integer userId = user.getId();
            Object object = SecurityUtils.getSubject().getSession().getAttribute(String.valueOf(userId));
            HotelUser userShiro = (HotelUser)object;
            Set<String> roleSet = userShiro.getRoles();
            Set<String> authSet = userShiro.getPermiss();
            SimpleAuthorizationInfo authorInfo = new SimpleAuthorizationInfo();
            authorInfo.setRoles(roleSet);
            authorInfo.setStringPermissions(authSet);
            return authorInfo;
        }
    
        @Override
        protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException {
            UsernamePasswordToken upt = (UsernamePasswordToken) token;
            String username = upt.getUsername();
            HotelUser user = userService.queryByUserName(username);
            if(null == user){
                throw new UnknownAccountException();
            }
            Integer userId = user.getId();
            user.setRoles(roleService.queryUserRoleByUserId(userId));
            user.setPermiss(permissionService.queryUserPermissByUserId(userId));
            SecurityUtils.getSubject().getSession().setAttribute(String.valueOf(userId),user);
            SimpleAuthenticationInfo authenticationInfo =
                    new SimpleAuthenticationInfo(user,user.getPassword(),getName());
            return authenticationInfo;
        }
    }
    
    
    1. Shiro 配置
    @Configuration
    public class ShiroConfig {
    
        @Bean(value = "shiroFilterFactoryBean")
        public ShiroFilterFactoryBean shiroFilter(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
            ShiroFilterFactoryBean shiroFilterFactoryBean = new ShiroFilterFactoryBean();
            shiroFilterFactoryBean.setSecurityManager(securityManager);
            shiroFilterFactoryBean.setLoginUrl("/");
            shiroFilterFactoryBean.setSuccessUrl("/index");
            shiroFilterFactoryBean.setUnauthorizedUrl("/unAuth");
            Map<String,String> filterMap = new LinkedHashMap<>();
            filterMap.put("/static/**","anon");
            filterMap.put("/templates/**","anon");
            filterMap.put("/login","anon");
            filterMap.put("/","anon");
            filterMap.put("/loginOut","logout");
            filterMap.put("/**","authc");
            shiroFilterFactoryBean.setFilterChainDefinitionMap(filterMap);
            return shiroFilterFactoryBean;
        }
    
        @Bean(value = "securityManager")
        public DefaultWebSecurityManager securityManager(@Qualifier("myShiroRealm")RealmShiro realm){
            DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();
            securityManager.setRealm(realm);
            return securityManager;
        }
    
        @Bean(value = "myShiroRealm")
        public RealmShiro myShiroRealm(){
            RealmShiro realmShiro = new RealmShiro();
            return realmShiro;
        }
    
        @Bean(value = "lifecycleBeanPostProcessor")
        public LifecycleBeanPostProcessor lifecycleBeanPostProcessor() {
            return new LifecycleBeanPostProcessor();
        }
    
    	//如果要使用 @RequiresPermissions和@RequiresRoles,则此处不可缺少
        @Bean
        @DependsOn("lifecycleBeanPostProcessor")
        @ConditionalOnMissingBean
        public DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator(){
            DefaultAdvisorAutoProxyCreator advisorAutoProxyCreator = new DefaultAdvisorAutoProxyCreator();
            advisorAutoProxyCreator.setProxyTargetClass(true);
            return advisorAutoProxyCreator;
        }
    
        @Bean
        public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor(@Qualifier("securityManager")DefaultWebSecurityManager securityManager){
            AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor();
            advisor.setSecurityManager(securityManager);
            return advisor;
        }
    }
    

    说明:

    认证过滤器:

    • anon:表示可以匿名使用
    • authc:表示需要认证(登录)才能使用,没有参数
    • authcBasic:没有参数表示httpBasic认证 ; user:当登入操作时不做检查

    授权过滤器:

    • roles:参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割;EQ:/admins/user/=roles[“admin,guest”],每个参数通过才算通过。
    • perms:参数可以写多个,多个时必须加上引号,并且参数之间用逗号分割;EQ:/admins/user/=perms[“user:add:,user:modify:”],当有多个参数时必须每个参数都通过才通过。
    1. 账号密码验证及登录功能
    @PostMapping("/login")
        @ResponseBody
        public Object login(String username, String password){
            if(StringUtils.isEmpty(username)){
                return ResultUtil.error("用户名为空");
            }
    
            if(StringUtils.isEmpty(password)){
                return ResultUtil.error("密码为空");
            }
            //注意以下代码
            Subject subject = SecurityUtils.getSubject();
            UsernamePasswordToken token = new UsernamePasswordToken(username,password);
            subject.login(token);
            
            return  ResultUtil.success("登录成功");
        }
    
    展开全文
  • golang常见字符串拼接通用处理方式

    千次阅读 2019-01-29 19:37:55
    golang常见字符串拼接处理方式1、参数名ASCII从小到大排序2.按照特定参数顺序拼接 我们在日常开发中,尤其是对接第三方登录、支付、分享等功能时, ...目前经常遇到排序方式主要有以下两种: ...
  • 校验码——循环冗余码CRC(主要用来检错) 商不重要!!数据+余数是最终CRC码。 CRC特点: 具有r检测位多项式能够检测出所有小于或等于r突发错误。 长度大于r+1错误逃脱率是1/2r1/2^r1/2r 校验码——海明...
  • 除png头以外,每一个数据块都是按照数据长度+数据标识符+CRC校验码的结构来组织。如下图: 二、主要的PNG数据块 PNG图片头信息用8个字节来唯一标识图像类型。 “89 50 4E 47 00 DA 1A 0A” 为png文件...
  • 打开超级终端,选择相应串口,将端口参数设置为:速率—4800、奇偶校验位—无、数据位—8、停止位—1、流量控制—硬件。 (2)连接测试 输入“AT”然后回车,屏幕上返回“OK”表明计算机与TC35T已连接成功,TC35T...
  •  Collection是集合类上级接口,继承与他接口主要有Set 和List. Collections是针对集合类一个帮助类,他提供一系列静态方法实现对各种集合搜索、排序、线程安全化等操作。 13、&和&&区别。 &是位运算符...
  • 计算机组成原理day4

    2020-07-18 03:00:53
    计算机组成原理辅助...一般常见的磁表面存储器: 硬磁盘 软磁盘 磁带 技术指标: 记录密度 存储容量 平均寻址时间 数据传输率 误码率 循环冗余校验码 循环冗余校验码可以发现并矫正信息在存储火传送过程中
  • MD5用途及写法

    2021-01-11 18:22:36
    常见的应用场景密码保护、下载文件校验等。 应用场景 防止数据库丢失带来的风险 如果将用户的账户密码等数据以明文的形式存放在数据库中,若数据库被人盗取,会产生用户信息暴露的麻烦,转换成MD5则无法恢复成...
  • 框架针对踢人下线、自动续签、前后台分离、分布式会话……等常见业务进行N多适配,通过sa-token,你可以以一种极简方式实现系统权限认证部分 与其它权限认证框架相比,sa-token 具有以下优势: 简单 :可零...
  • 本文摘录自《Nodejs学习笔记》,更多章节及更新,请访问 github主页地址。欢迎加群交流,群号 ...常见的应用场景密码保护、下载文件校验等。 本文先对MD5的特点与应用进行简要概述,接着重点介绍MD5在密码保护场...
  • LCD电路,为了能直观的看到生成的密码,以及用户输入的密码,就需要一个显示设备,而在单片机系统中,比较常见的显示设备就是LED和LCD,相比较于LED来说,LCD显示效果更加美观,更加真实; 按键电路,为了做到密码的...
  • 44、请写出你最常见5个runtime exception。 28 45、JAVA语言如何进行异常处理,关键字:throws,throw,try,catch,finally分别代表什么意义?在try块中可以抛出异常吗? 29 46、java中几种方法可以实现一个线程...
  • linux/openssl

    2015-12-21 15:17:05
    单向加密单向加密是计算一段数据的特征,利用特征对数据完整性进行校验,且输出定长。常见的加密算法MD5、SHA1。对称加密对称加密就是加密和解密使用相同的密钥。常见的算法DES、AES、3DES。非对称加密加密...
  • 而使用表现层框架则可以将Jsp中剩余JavaBeans完全分离,这部分JavaBeans主要负责显示相关信息,一般是通过标签库(Taglib)实现,不同框架不同自己标签库,Struts是应用比较广泛一种表现层框架。 2、 Ajax...
  • 已经8756个初学者都下载了!三歪把【大厂面试知识点】、【简历模板】、【原创文章】全部整理成电子书,共有1263页!...主要是我可以通过这个打赏情况来看我心血没有价值,嘻嘻。 全网最低价...
  • 个人总结:这篇文章讲解了Nodejs中自带模块的MD5加密算法的使用,读完这篇文章需要15分钟,其实还有一个叫utility的包在npm上,也非常好用。...常见的应用场景密码保护、下载文件校验等。 本文先对...
  • 配置管理熟称OMACP,它是一个接收运营商配置的应用,主要接收WebXml数据,比较常见的有APN配置和Email配置,下面我们从MTK的源代码简单分析下相关业务流程。 MTK配置管理业务的大致流程如下:首先运营商下发xml配置...
  • GoodProject Maven Webapp.zip

    2019-05-12 14:06:27
    1:数据访问层:主要看数据层里面没有包含逻辑处理,实际上它各个函数主要完成各个对数据文件操作。而不必管其他操作。 2:业务逻辑层:主要负责对数据层操作。也就是说把一些数据层操作进行组合。 3:表示层:...
  • 用刻录软件,选择 映像刻录 方式来刻录ISO文件,刻录前请先校验一下文件准确性,刻录速度推荐24X! 在BIOS中设置光驱启动,选择第一项即可自动安装到硬盘第一分区。隐藏分区品牌机建议手动安装。 2、硬盘...

空空如也

空空如也

1 2 3 4 5 6
收藏数 106
精华内容 42
关键字:

常见的校验码主要有