Commit abc82060 by chentianzhong

代码提交

parent 86de89bf
{
"presets": [
["env", {
"modules": false,
"targets": {
"browsers": ["> 1%", "last 2 versions", "not ie <= 8"]
}
}],
"stage-2"
],
"plugins": ["transform-vue-jsx", "transform-runtime"]
}
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
// https://eslint.org/docs/user-guide/configuring
module.exports = {
root: true,
parserOptions: {
parser: 'babel-eslint'
},
env: {
browser: true,
},
extends: [
// https://github.com/vuejs/eslint-plugin-vue#priority-a-essential-error-prevention
// consider switching to `plugin:vue/strongly-recommended` or `plugin:vue/recommended` for stricter rules.
'plugin:vue/essential',
// https://github.com/standard/standard/blob/master/docs/RULES-en.md
'standard'
],
// required to lint *.vue files
plugins: [
'vue'
],
// add your custom rules here
rules: {
// allow async-await
'generator-star-spacing': 'off',
// allow debugger during development
'no-debugger': process.env.NODE_ENV === 'production' ? 'error' : 'off'
}
}
.DS_Store
node_modules/
/dist/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
// https://github.com/michael-ciniawsky/postcss-load-config
module.exports = {
"plugins": {
"postcss-import": {},
"postcss-url": {},
// to edit target browsers: use "browserslist" field in package.json
"autoprefixer": {}
}
}
# vue2-gxca
> A Vue.js project
## Build Setup
``` bash
# install dependencies
npm install
# serve with hot reload at localhost:8080
npm run dev
# build for production with minification
npm run build
# build for production and view the bundle analyzer report
npm run build --report
```
For a detailed explanation on how things work, check out the [guide](http://vuejs-templates.github.io/webpack/) and [docs for vue-loader](http://vuejs.github.io/vue-loader).
'use strict'
require('./check-versions')()
process.env.NODE_ENV = 'production'
const ora = require('ora')
const rm = require('rimraf')
const path = require('path')
const chalk = require('chalk')
const webpack = require('webpack')
const config = require('../config')
const webpackConfig = require('./webpack.prod.conf')
const spinner = ora('building for production...')
spinner.start()
rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => {
if (err) throw err
webpack(webpackConfig, (err, stats) => {
spinner.stop()
if (err) throw err
process.stdout.write(stats.toString({
colors: true,
modules: false,
children: false, // If you are using ts-loader, setting this to true will make TypeScript errors show up during build.
chunks: false,
chunkModules: false
}) + '\n\n')
if (stats.hasErrors()) {
console.log(chalk.red(' Build failed with errors.\n'))
process.exit(1)
}
console.log(chalk.cyan(' Build complete.\n'))
console.log(chalk.yellow(
' Tip: built files are meant to be served over an HTTP server.\n' +
' Opening index.html over file:// won\'t work.\n'
))
})
})
'use strict'
const chalk = require('chalk')
const semver = require('semver')
const packageConfig = require('../package.json')
const shell = require('shelljs')
function exec (cmd) {
return require('child_process').execSync(cmd).toString().trim()
}
const versionRequirements = [
{
name: 'node',
currentVersion: semver.clean(process.version),
versionRequirement: packageConfig.engines.node
}
]
if (shell.which('npm')) {
versionRequirements.push({
name: 'npm',
currentVersion: exec('npm --version'),
versionRequirement: packageConfig.engines.npm
})
}
module.exports = function () {
const warnings = []
for (let i = 0; i < versionRequirements.length; i++) {
const mod = versionRequirements[i]
if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) {
warnings.push(mod.name + ': ' +
chalk.red(mod.currentVersion) + ' should be ' +
chalk.green(mod.versionRequirement)
)
}
}
if (warnings.length) {
console.log('')
console.log(chalk.yellow('To use this template, you must update following to modules:'))
console.log()
for (let i = 0; i < warnings.length; i++) {
const warning = warnings[i]
console.log(' ' + warning)
}
console.log()
process.exit(1)
}
}
'use strict'
const path = require('path')
const config = require('../config')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const packageConfig = require('../package.json')
exports.assetsPath = function (_path) {
const assetsSubDirectory = process.env.NODE_ENV === 'production'
? config.build.assetsSubDirectory
: config.dev.assetsSubDirectory
return path.posix.join(assetsSubDirectory, _path)
}
exports.cssLoaders = function (options) {
options = options || {}
const cssLoader = {
loader: 'css-loader',
options: {
sourceMap: options.sourceMap
}
}
const postcssLoader = {
loader: 'postcss-loader',
options: {
sourceMap: options.sourceMap
}
}
// generate loader string to be used with extract text plugin
function generateLoaders (loader, loaderOptions) {
const loaders = options.usePostCSS ? [cssLoader, postcssLoader] : [cssLoader]
if (loader) {
loaders.push({
loader: loader + '-loader',
options: Object.assign({}, loaderOptions, {
sourceMap: options.sourceMap
})
})
}
// Extract CSS when that option is specified
// (which is the case during production build)
if (options.extract) {
return ExtractTextPlugin.extract({
use: loaders,
fallback: 'vue-style-loader'
})
} else {
return ['vue-style-loader'].concat(loaders)
}
}
// https://vue-loader.vuejs.org/en/configurations/extract-css.html
return {
css: generateLoaders(),
postcss: generateLoaders(),
less: generateLoaders('less'),
sass: generateLoaders('sass', { indentedSyntax: true }),
scss: generateLoaders('sass'),
stylus: generateLoaders('stylus'),
styl: generateLoaders('stylus')
}
}
// Generate loaders for standalone style files (outside of .vue)
exports.styleLoaders = function (options) {
const output = []
const loaders = exports.cssLoaders(options)
for (const extension in loaders) {
const loader = loaders[extension]
output.push({
test: new RegExp('\\.' + extension + '$'),
use: loader
})
}
return output
}
exports.createNotifierCallback = () => {
const notifier = require('node-notifier')
return (severity, errors) => {
if (severity !== 'error') return
const error = errors[0]
const filename = error.file && error.file.split('!').pop()
notifier.notify({
title: packageConfig.name,
message: severity + ': ' + error.name,
subtitle: filename || '',
icon: path.join(__dirname, 'logo.png')
})
}
}
'use strict'
const utils = require('./utils')
const config = require('../config')
const isProduction = process.env.NODE_ENV === 'production'
const sourceMapEnabled = isProduction
? config.build.productionSourceMap
: config.dev.cssSourceMap
module.exports = {
loaders: utils.cssLoaders({
sourceMap: sourceMapEnabled,
extract: isProduction
}),
cssSourceMap: sourceMapEnabled,
cacheBusting: config.dev.cacheBusting,
transformToRequire: {
video: ['src', 'poster'],
source: 'src',
img: 'src',
image: 'xlink:href'
}
}
'use strict'
const path = require('path')
const utils = require('./utils')
const config = require('../config')
const vueLoaderConfig = require('./vue-loader.conf')
function resolve (dir) {
return path.join(__dirname, '..', dir)
}
const createLintingRule = () => ({
test: /\.(js|vue)$/,
loader: 'eslint-loader',
enforce: 'pre',
include: [resolve('src'), resolve('test')],
options: {
formatter: require('eslint-friendly-formatter'),
emitWarning: !config.dev.showEslintErrorsInOverlay
}
})
module.exports = {
context: path.resolve(__dirname, '../'),
entry: {
app: './src/main.js'
},
output: {
path: config.build.assetsRoot,
filename: '[name].js',
publicPath: process.env.NODE_ENV === 'production'
? config.build.assetsPublicPath
: config.dev.assetsPublicPath
},
resolve: {
extensions: ['.js', '.vue', '.json'],
alias: {
'vue$': 'vue/dist/vue.esm.js',
'@': resolve('src'),
}
},
module: {
rules: [
...(config.dev.useEslint ? [createLintingRule()] : []),
{
test: /\.vue$/,
loader: 'vue-loader',
options: vueLoaderConfig
},
{
test: /\.js$/,
loader: 'babel-loader',
include: [resolve('src'), resolve('test'), resolve('node_modules/webpack-dev-server/client')]
},
{
test: /\.(png|jpe?g|gif|svg)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('img/[name].[hash:7].[ext]')
}
},
{
test: /\.(mp4|webm|ogg|mp3|wav|flac|aac)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('media/[name].[hash:7].[ext]')
}
},
{
test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/,
loader: 'url-loader',
options: {
limit: 10000,
name: utils.assetsPath('fonts/[name].[hash:7].[ext]')
}
}
]
},
node: {
// prevent webpack from injecting useless setImmediate polyfill because Vue
// source contains it (although only uses it if it's native).
setImmediate: false,
// prevent webpack from injecting mocks to Node native modules
// that does not make sense for the client
dgram: 'empty',
fs: 'empty',
net: 'empty',
tls: 'empty',
child_process: 'empty'
}
}
'use strict'
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const path = require('path')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin')
const portfinder = require('portfinder')
const HOST = process.env.HOST
const PORT = process.env.PORT && Number(process.env.PORT)
const devWebpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap, usePostCSS: true })
},
// cheap-module-eval-source-map is faster for development
devtool: config.dev.devtool,
// these devServer options should be customized in /config/index.js
devServer: {
clientLogLevel: 'warning',
historyApiFallback: {
rewrites: [
{ from: /.*/, to: path.posix.join(config.dev.assetsPublicPath, 'index.html') },
],
},
hot: true,
contentBase: false, // since we use CopyWebpackPlugin.
compress: true,
host: HOST || config.dev.host,
port: PORT || config.dev.port,
open: config.dev.autoOpenBrowser,
overlay: config.dev.errorOverlay
? { warnings: false, errors: true }
: false,
publicPath: config.dev.assetsPublicPath,
proxy: config.dev.proxyTable,
quiet: true, // necessary for FriendlyErrorsPlugin
watchOptions: {
poll: config.dev.poll,
}
},
plugins: [
new webpack.DefinePlugin({
'process.env': require('../config/dev.env')
}),
new webpack.HotModuleReplacementPlugin(),
new webpack.NamedModulesPlugin(), // HMR shows correct file names in console on update.
new webpack.NoEmitOnErrorsPlugin(),
// https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: 'index.html',
template: 'index.html',
inject: true
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.dev.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
module.exports = new Promise((resolve, reject) => {
portfinder.basePort = process.env.PORT || config.dev.port
portfinder.getPort((err, port) => {
if (err) {
reject(err)
} else {
// publish the new Port, necessary for e2e tests
process.env.PORT = port
// add port to devServer config
devWebpackConfig.devServer.port = port
// Add FriendlyErrorsPlugin
devWebpackConfig.plugins.push(new FriendlyErrorsPlugin({
compilationSuccessInfo: {
messages: [`Your application is running here: http://${devWebpackConfig.devServer.host}:${port}`],
},
onErrors: config.dev.notifyOnErrors
? utils.createNotifierCallback()
: undefined
}))
resolve(devWebpackConfig)
}
})
})
'use strict'
const path = require('path')
const utils = require('./utils')
const webpack = require('webpack')
const config = require('../config')
const merge = require('webpack-merge')
const baseWebpackConfig = require('./webpack.base.conf')
const CopyWebpackPlugin = require('copy-webpack-plugin')
const HtmlWebpackPlugin = require('html-webpack-plugin')
const ExtractTextPlugin = require('extract-text-webpack-plugin')
const OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin')
const UglifyJsPlugin = require('uglifyjs-webpack-plugin')
const env = require('../config/prod.env')
const webpackConfig = merge(baseWebpackConfig, {
module: {
rules: utils.styleLoaders({
sourceMap: config.build.productionSourceMap,
extract: true,
usePostCSS: true
})
},
devtool: config.build.productionSourceMap ? config.build.devtool : false,
output: {
path: config.build.assetsRoot,
filename: utils.assetsPath('js/[name].[chunkhash].js'),
chunkFilename: utils.assetsPath('js/[id].[chunkhash].js')
},
plugins: [
// http://vuejs.github.io/vue-loader/en/workflow/production.html
new webpack.DefinePlugin({
'process.env': env
}),
new UglifyJsPlugin({
uglifyOptions: {
compress: {
warnings: false
}
},
sourceMap: config.build.productionSourceMap,
parallel: true
}),
// extract css into its own file
new ExtractTextPlugin({
filename: utils.assetsPath('css/[name].[contenthash].css'),
// Setting the following option to `false` will not extract CSS from codesplit chunks.
// Their CSS will instead be inserted dynamically with style-loader when the codesplit chunk has been loaded by webpack.
// It's currently set to `true` because we are seeing that sourcemaps are included in the codesplit bundle as well when it's `false`,
// increasing file size: https://github.com/vuejs-templates/webpack/issues/1110
allChunks: true,
}),
// Compress extracted CSS. We are using this plugin so that possible
// duplicated CSS from different components can be deduped.
new OptimizeCSSPlugin({
cssProcessorOptions: config.build.productionSourceMap
? { safe: true, map: { inline: false } }
: { safe: true }
}),
// generate dist index.html with correct asset hash for caching.
// you can customize output by editing /index.html
// see https://github.com/ampedandwired/html-webpack-plugin
new HtmlWebpackPlugin({
filename: config.build.index,
template: 'index.html',
inject: true,
minify: {
removeComments: true,
collapseWhitespace: true,
removeAttributeQuotes: true
// more options:
// https://github.com/kangax/html-minifier#options-quick-reference
},
// necessary to consistently work with multiple chunks via CommonsChunkPlugin
chunksSortMode: 'dependency'
}),
// keep module.id stable when vendor modules does not change
new webpack.HashedModuleIdsPlugin(),
// enable scope hoisting
new webpack.optimize.ModuleConcatenationPlugin(),
// split vendor js into its own file
new webpack.optimize.CommonsChunkPlugin({
name: 'vendor',
minChunks (module) {
// any required modules inside node_modules are extracted to vendor
return (
module.resource &&
/\.js$/.test(module.resource) &&
module.resource.indexOf(
path.join(__dirname, '../node_modules')
) === 0
)
}
}),
// extract webpack runtime and module manifest to its own file in order to
// prevent vendor hash from being updated whenever app bundle is updated
new webpack.optimize.CommonsChunkPlugin({
name: 'manifest',
minChunks: Infinity
}),
// This instance extracts shared chunks from code splitted chunks and bundles them
// in a separate chunk, similar to the vendor chunk
// see: https://webpack.js.org/plugins/commons-chunk-plugin/#extra-async-commons-chunk
new webpack.optimize.CommonsChunkPlugin({
name: 'app',
async: 'vendor-async',
children: true,
minChunks: 3
}),
// copy custom static assets
new CopyWebpackPlugin([
{
from: path.resolve(__dirname, '../static'),
to: config.build.assetsSubDirectory,
ignore: ['.*']
}
])
]
})
if (config.build.productionGzip) {
const CompressionWebpackPlugin = require('compression-webpack-plugin')
webpackConfig.plugins.push(
new CompressionWebpackPlugin({
asset: '[path].gz[query]',
algorithm: 'gzip',
test: new RegExp(
'\\.(' +
config.build.productionGzipExtensions.join('|') +
')$'
),
threshold: 10240,
minRatio: 0.8
})
)
}
if (config.build.bundleAnalyzerReport) {
const BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin
webpackConfig.plugins.push(new BundleAnalyzerPlugin())
}
module.exports = webpackConfig
'use strict'
const merge = require('webpack-merge')
const prodEnv = require('./prod.env')
module.exports = merge(prodEnv, {
NODE_ENV: '"development"'
})
'use strict'
// Template version: 1.3.1
// see http://vuejs-templates.github.io/webpack for documentation.
const path = require('path')
module.exports = {
dev: {
// Paths
assetsSubDirectory: 'static',
assetsPublicPath: '/',
proxyTable: {},
// Various Dev Server settings
host: 'localhost', // can be overwritten by process.env.HOST
port: 8080, // can be overwritten by process.env.PORT, if port is in use, a free one will be determined
autoOpenBrowser: false,
errorOverlay: true,
notifyOnErrors: true,
poll: false, // https://webpack.js.org/configuration/dev-server/#devserver-watchoptions-
// Use Eslint Loader?
// If true, your code will be linted during bundling and
// linting errors and warnings will be shown in the console.
useEslint: true,
// If true, eslint errors and warnings will also be shown in the error overlay
// in the browser.
showEslintErrorsInOverlay: false,
/**
* Source Maps
*/
// https://webpack.js.org/configuration/devtool/#development
devtool: 'cheap-module-eval-source-map',
// If you have problems debugging vue-files in devtools,
// set this to false - it *may* help
// https://vue-loader.vuejs.org/en/options.html#cachebusting
cacheBusting: true,
cssSourceMap: true
},
build: {
// Template for index.html
index: path.resolve(__dirname, '../dist/index.html'),
// Paths
assetsRoot: path.resolve(__dirname, '../dist'),
assetsSubDirectory: 'static',
assetsPublicPath: '/',
/**
* Source Maps
*/
productionSourceMap: true,
// https://webpack.js.org/configuration/devtool/#production
devtool: '#source-map',
// Gzip off by default as many popular static hosts such as
// Surge or Netlify already gzip all static assets for you.
// Before setting to `true`, make sure to:
// npm install --save-dev compression-webpack-plugin
productionGzip: false,
productionGzipExtensions: ['js', 'css'],
// Run the build command with an extra argument to
// View the bundle analyzer report after build finishes:
// `npm run build --report`
// Set to `true` or `false` to always turn it on or off
bundleAnalyzerReport: process.env.npm_config_report
}
}
'use strict'
module.exports = {
NODE_ENV: '"production"'
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title>vue2-gxca</title>
</head>
<body>
<div id="app"></div>
<!-- built files will be auto injected -->
<script src="./static/js/XTXSAB.js"></script>
</body>
</html>
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "vue2-gxca",
"version": "1.0.0",
"description": "A Vue.js project",
"author": "天气不坏 <674858232@qq.com>",
"private": true,
"scripts": {
"dev": "webpack-dev-server --inline --progress --config build/webpack.dev.conf.js",
"start": "npm run dev",
"lint": "eslint --ext .js,.vue src",
"build": "node build/build.js"
},
"dependencies": {
"vue": "^2.5.2"
},
"devDependencies": {
"autoprefixer": "^7.1.2",
"babel-core": "^6.22.1",
"babel-eslint": "^8.2.1",
"babel-helper-vue-jsx-merge-props": "^2.0.3",
"babel-loader": "^7.1.1",
"babel-plugin-syntax-jsx": "^6.18.0",
"babel-plugin-transform-runtime": "^6.22.0",
"babel-plugin-transform-vue-jsx": "^3.5.0",
"babel-preset-env": "^1.3.2",
"babel-preset-stage-2": "^6.22.0",
"chalk": "^2.0.1",
"copy-webpack-plugin": "^4.0.1",
"css-loader": "^0.28.0",
"eslint": "^4.15.0",
"eslint-config-standard": "^10.2.1",
"eslint-friendly-formatter": "^3.0.0",
"eslint-loader": "^1.7.1",
"eslint-plugin-import": "^2.7.0",
"eslint-plugin-node": "^5.2.0",
"eslint-plugin-promise": "^3.4.0",
"eslint-plugin-standard": "^3.0.1",
"eslint-plugin-vue": "^4.0.0",
"extract-text-webpack-plugin": "^3.0.0",
"file-loader": "^1.1.4",
"friendly-errors-webpack-plugin": "^1.6.1",
"html-webpack-plugin": "^2.30.1",
"node-notifier": "^5.1.2",
"optimize-css-assets-webpack-plugin": "^3.2.0",
"ora": "^1.2.0",
"portfinder": "^1.0.13",
"postcss-import": "^11.0.0",
"postcss-loader": "^2.0.8",
"postcss-url": "^7.2.1",
"rimraf": "^2.6.0",
"semver": "^5.3.0",
"shelljs": "^0.7.6",
"uglifyjs-webpack-plugin": "^1.1.1",
"url-loader": "^0.5.8",
"vue-loader": "^13.3.0",
"vue-style-loader": "^3.0.1",
"vue-template-compiler": "^2.5.2",
"webpack": "^3.6.0",
"webpack-bundle-analyzer": "^2.9.0",
"webpack-dev-server": "^2.9.1",
"webpack-merge": "^4.1.0"
},
"engines": {
"node": ">= 6.0.0",
"npm": ">= 3.0.0"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
]
}
<template>
<div id="app">
<Login/>
</div>
</template>
<script>
import Login from './components/Login'
export default {
name: 'App',
components: {
Login
}
}
</script>
<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>
<template>
<div>
<span>用户</span> <select id="UserList"></select>
<br/>
<span>密码</span><input type="password" v-model="pin"/>
<button @click="doLogin()">登陆</button>
<br>
</div>
</template>
<script>
export default {
name: 'Login',
data () {
return {
pin: "",//用户证书密码
}
},
methods:{
//注意,由于方法都是异步的,所以需要在我们的回调方法中按步骤继续执行我们的回调,请不要改变方法位置和调用顺序
doLogin(){
//获取当前选中的用户的certid,双向数据绑定会有问题,所以通过元素获取
let strCertID = document.getElementById("UserList").options[0].value;
if(strCertID === "" || this.pin === ""){
alert('请插入ukey和输入PIN码');
return;
}
//1.通过ajax获取到后端传过来的 strServerSignedData,strServerRan和strServerCert,这步建议是在用户打开页面就自动获取,建议放在钩子函数中
//注意这里为了演示,直接写死,实际是必须从后台获取的
alert("通过ajax获取到后端传过来的 strServerSignedData,strServerRan和strServerCert---实际集成请去掉这个提示");
////后端返回的服务器签名值
let strServerSignedData = "MEUCIQCM+ewmele4KSNY7HmnYGQGXleZgDKVDtpGPeV8dvgQjAIgTnExY4GYQ9LuAD8MeWtXwT/hFHkBAqbp6xcxilB6Dpc=";
//后端返回的随机数
let strServerRan = "YPy8ujSXOcRKJ6NG5SCIK553kQGhx7TJ";
//后端返回的服务器证书
let strServerCert = "MIIEqTCCBE+gAwIBAgIKGhAAAAAAAO13RzAKBggqgRzPVQGDdTBEMQswCQYDVQQGEwJDTjENMAsGA1UECgwEQkpDQTENMAsGA1UECwwEQkpDQTEXMBUGA1UEAwwOQmVpamluZyBTTTIgQ0EwHhcNMTkwMjEzMTYwMDAwWhcNMjkwMjE0MTU1OTU5WjCBpTEbMBkGA1UEKQwSOTE0NTAwMDBNQTVONk4yRzZSMScwJQYDVQQDDB7mlbDlrZflub/opb/pm4blm6LmnInpmZDlhazlj7gxGDAWBgNVBAsMD0RTMjIzRzIxOTAxMDU5NTENMAsGA1UECgwEQkpDQTEnMCUGA1UECgwe5pWw5a2X5bm/6KW/6ZuG5Zui5pyJ6ZmQ5YWs5Y+4MQswCQYDVQQGDAJDTjBZMBMGByqGSM49AgEGCCqBHM9VAYItA0IABOUVr0Z8+Y94QFQ517F/isnioF0FDCrxDJ+qKqK20oINoH5kWbEJ79lPj0SBS0ZZ9pnAjmJYA72ArhTRb0kZlzajggLFMIICwTAfBgNVHSMEGDAWgBQf5s/Uj8UiKpdKKYoV5xbJkjTEtjAdBgNVHQ4EFgQU+1DevoKKaWEtTj/3gwhwDGQmHnwwCwYDVR0PBAQDAgbAMIGdBgNVHR8EgZUwgZIwYKBeoFykWjBYMQswCQYDVQQGEwJDTjENMAsGA1UECgwEQkpDQTENMAsGA1UECwwEQkpDQTEXMBUGA1UEAwwOQmVpamluZyBTTTIgQ0ExEjAQBgNVBAMTCWNhMjFjcmw3OTAuoCygKoYoaHR0cDovL2NybC5iamNhLm9yZy5jbi9jcmwvY2EyMWNybDc5LmNybDAkBgoqgRyG7zICAQEBBBYMFEpKOTE0NTAwMDBNQTVONk4yRzZSMGAGCCsGAQUFBwEBBFQwUjAjBggrBgEFBQcwAYYXT0NTUDovL29jc3AuYmpjYS5vcmcuY24wKwYIKwYBBQUHMAKGH2h0dHA6Ly9jcmwuYmpjYS5vcmcuY24vY2Fpc3N1ZXIwQAYDVR0gBDkwNzA1BgkqgRyG7zICAgEwKDAmBggrBgEFBQcCARYaaHR0cDovL3d3dy5iamNhLm9yZy5jbi9jcHMwEQYJYIZIAYb4QgEBBAQDAgD/MCIGCiqBHIbvMgIBAQgEFAwSOTE0NTAwMDBNQTVONk4yRzZSMCQGCiqBHIbvMgIBAgIEFgwUSko5MTQ1MDAwME1BNU42TjJHNlIwHwYKKoEchu8yAgEBDgQRDA8xMDIwODAwMDIyNzY3MDIwJAYKKoEchu8yAgEBBAQWDBRKSjkxNDUwMDAwTUE1TjZOMkc2UjAtBgoqgRyG7zICAQEXBB8MHTJAMjE1MDA5SkowOTE0NTAwMDBNQTVONk4yRzZSMCAGCCqBHNAUBAEEBBQMEjkxNDUwMDAwTUE1TjZOMkc2UjATBgoqgRyG7zICAQEeBAUMAzY1NDAKBggqgRzPVQGDdQNIADBFAiEAqclRpfLB92JYG7SUCGlxnQOpzengk2HYo9b8kXq6LxoCID0xO+vOVqmt1RzhWiB2t3+pVEDHqWONZUFmMHL/nV4e";
if(strServerSignedData === "" || strServerRan === "" || strServerCert === ""){
alert('连接CA服务器失败,请刷新页面重试!');
return;
}
//2.校验证书密码
VerifyUserPIN(strCertID, this.pin, function(retObj) {
if (!retObj.retVal) { //校验失败
//2.1获取PIN剩余次数
GetUserPINRetryCount(strCertID, function (retObj){
var retryCount = Number(retObj.retVal);
if (retryCount > 0) {
alert("校验证书密码失败!您还有" + retryCount + "次机会重试!");
return;
} else if (retryCount == 0) {
alert("您的证书密码已被锁死,请联系管理员进行解锁!");
return;
} else {
alert("登录失败!");
return;
}
});
} else{
//校验pin码成功,继续往下执行
//3、获取用户证书
GetSignCert(strCertID, function(retObj){
var UserCert = retObj.retVal;
if (UserCert == "") {
alert("获取签名证书失败!");
return;
}else {
//4.验证服务端签名
VerifySignedData(strServerCert,strServerRan,strServerSignedData,function(retObj){
if (!retObj.retVal) {
alert("验证服务端签名失败!");
return;
}else{
//5、客户端对服务器随机数签名
SignedData(strCertID, strServerRan, function(retObj){
if (retObj.retVal == "") {
alert("客户端签名失败!");
return;
}else{
var UserSignedData = retObj.retVal;
//在此处写你的代码,把UserCert,strServerRan,UserSignedData等传到后台验证
//6、通过ajax把 UserCert,strServerRan,UserSignedData传到后台,由后台解析验证,判断用户是否有权限登陆系统
alert("通过ajax把 UserCert,strServerRan,UserSignedData传到后台,由后台解析验证,判断用户是否有权限登陆系统");
}
});
}
});
}
});
}
});
}
},
mounted() {
//调用
SetUserCertList("UserList", CERT_TYPE_HARD);
}
}
</script>
<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped>
h1, h2 {
font-weight: normal;
}
ul {
list-style-type: none;
padding: 0;
}
li {
display: inline-block;
margin: 0 10px;
}
a {
color: #42b983;
}
</style>
// The Vue build version to load with the `import` command
// (runtime-only or standalone) has been set in webpack.base.conf with an alias.
import Vue from 'vue'
import App from './App'
Vue.config.productionTip = false
/* eslint-disable no-new */
new Vue({
el: '#app',
components: { App },
template: '<App/>'
})
var DSVSCaller = new function() {
var DSVSCaller = new function() {
// call dsvs
this.CallDSVS = function(plain, userCert, signedData, showResID) {
var xmlHttp = this.CreateXMLHtpp();
xmlHttp.onreadystatechange = function() {
if (xmlHttp.readyState == 4) {
var resID = document.getElementById(showResID);
if (xmlHttp.responseText == "true") {
resID.style.color = 'black';
resID.value = "服务端验证签名成功!";
} else if (xmlHttp.responseText == "false") {
resID.style.color = 'red';
resID.value = "服务端验证签名失败!";
}
}
}
var postParam = "";
postParam = this.addURLParam(postParam, "plain", plain);
postParam = this.addURLParam(postParam, "userCert", userCert);
postParam = this.addURLParam(postParam, "signedData", signedData);
postParam = encodeURI(postParam);
//alert(postParam);
xmlHttp.open("POST", "../DSVSCode.jsp", true);
xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded");
xmlHttp.send(postParam);
}
//用于创建XMLHttpRequest对象
this.CreateXMLHtpp = function() {
var xmlHttp = null;
//根据window.XMLHttpRequest对象是否存在使用不同的创建方式
if (window.XMLHttpRequest) {
xmlHttp = new XMLHttpRequest(); //FireFox、Opera等浏览器支持的创建方式
} else {
xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");//IE浏览器支持的创建方式
}
return xmlHttp;
}
this.addURLParam = function(url, name, value) {
//url += url.indexOf("?") == -1 ? "?" : "&";
if (url != "") {
url += "&";
}
url += encodeURIComponent(name) + "=" + encodeURIComponent(value);
return url;
}
}
\ No newline at end of file
<%@page contentType="text/plain; charset=UTF-8"%>
<%@page contentType="text/plain; charset=UTF-8"%>
<%@include file="properties.jsp"%>
<%@ page language="java"%>
<%
out.clear();
request.setCharacterEncoding("UTF-8");
String plain = request.getParameter("plain"); //获取到签名原文
String userCert = request.getParameter("userCert"); //获取到ukey用户证书
String signedData = request.getParameter("signedData"); //获取到签名值
if (plain != null && plain != "") {
plain = java.net.URLDecoder.decode(plain);
}
if (userCert != null && userCert != "") {
userCert = java.net.URLDecoder.decode(userCert, "UTF-8");
}
if (signedData != null && signedData != "") {
signedData = java.net.URLDecoder.decode(signedData, "UTF-8");
}
String strRes = "";
try {
//验证签名
boolean bRet = sed.verifySignedData(userCert, plain.getBytes(), sed.base64Decode(signedData));
if (bRet) {
strRes = "true";
} else {
strRes = "false";
}
System.out.println("verifySignedData->Result:" + strRes);
out.print(strRes);
//验证签名成功之后,把 plain,userCert和signedData存到数据库中
} catch (Exception e) {
System.out.println("Exception..." + e.getMessage());
out.print("");
}
%>
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8" ?>
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE struts PUBLIC
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
"http://struts.apache.org/dtds/struts-2.0.dtd">
<struts>
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
<constant name="struts.devMode" value="false" />
<!-- Add packages here -->
</struts>
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 5.0//EN"
<!DOCTYPE jboss-web PUBLIC "-//JBoss//DTD Web Application 5.0//EN"
"http://www.jboss.org/j2ee/dtd/jboss-web_5_0.dtd">
<jboss-web>
<class-loading java2ClassLoadingCompliance='true'>
<loader-repository>
com.example:archive=unique-archive-name
<loader-repository-config>
java2ParentDelegaton=true
</loader-repository-config>
</loader-repository>
</class-loading>
</jboss-web>
\ No newline at end of file
<?xml version="1.0" ?>
<?xml version="1.0" ?>
<!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">
<web-app>
</web-app>
<!DOCTYPE weblogic-web-app PUBLIC "-//BEA
<!DOCTYPE weblogic-web-app PUBLIC "-//BEA
Systems, Inc.//DTD Web Application 8.1//EN"
"http://www.bea.com/servers/wls810/dtd/weblogic810-web-jar.dtd">
<weblogic-web-app>
<container-descriptor>
<prefer-web-inf-classes>true</prefer-web-inf-classes>
</container-descriptor>
</weblogic-web-app>
<table width="958" border="0" align="center" cellpadding="0"
<table width="958" border="0" align="center" cellpadding="0"
cellspacing="0">
<tr>
<td height="10" bgcolor="#FEFDFB">
&nbsp;
</td>
</tr>
<tr>
<td height="2" bgcolor="#E19FA3"></td>
</tr>
<tr>
<td width="958" height="30" align="center" class="font2">
</td>
</tr>
</table>
\ No newline at end of file
<%@page contentType="text/html; charset=UTF-8"%>
<%@page contentType="text/html; charset=UTF-8"%>
<%@include file="../properties.jsp"%>
<%
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.flushBuffer();
//判断session是否失效
String strCertName = (String) session.getAttribute("CertName");
if (strCertName == null || strCertName.equals("")) {
response.sendRedirect("../index.jsp");
}
//获得登陆用户CertID
String strCertID = (String) session.getAttribute("CertID");
%>
<html>
<head>
<title>证书应用演示环境</title>
<style type="text/css">
</style>
<link href="../style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<%@include file="../top.jsp"%>
<table width="957" border="0" align="center" cellpadding="0"cellspacing="0">
<tr>
<td bgcolor="#FEFDFB">
&nbsp;
</td>
</tr>
<tr>
<td width="267" align="left" valign="top">
<%@include file="../form.jsp"%>
</td>
<td align="left" valign="top" bgcolor="#FEFDFB">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
&nbsp;
</td>
<td class="font1">
<img src="../images/jt.gif" width="12" height="12" />
数据加密功能演示
</td>
</tr>
<tr>
<td height="5"></td>
</tr>
<tr height="2">
<td></td>
<td>
<table width="100%" height="2" border="0" cellpadding="0"
cellspacing="0">
<tr>
<td height="2" bgcolor="#CCCCCC"></td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="10"></td>
</tr>
<tr>
<td>
&nbsp;
</td>
<td align="left" valign="top">
<form method="post" ID="TestForm">
<table width="98%" border="0" align="center" cellpadding="5"
cellspacing="1" class="table1">
<tr>
<td style="font-size:14px;" width="35%">
需要加密的数据:
</td>
<td style="font-size:14px;">
<textarea name=plainData id=plainData cols="40" rows="6" >写入需要加密的数据!</textarea>
</td>
</tr>
<tr>
<td>
<input type="button" value="加密" class="button" style="width:50px;" onClick="pubicKeyEncData();">
</td>
<td style="font-size:14px;">
<textarea name=cipherData id=cipherData cols="40" rows="6">加密后的结果显示!</textarea>
</td>
</tr>
<tr>
<td>
<input type="button" name="B13" value="解密" style="width:50px;" class="button"
width="55" height="28" onClick="prikeyDecryptData();return false;">
</td>
<td style="font-size:14px;">
<textarea name=decryptData id=decryptData cols="40" rows="6">解密后结果显示!</textarea>
</td>
</tr>
<tr>
<td>
<input type="button" name="B13" value="比较" style="width:50px;" class="button"
width="55" height="28" onClick="CompareData();return false;">
</td>
<td style="font-size:14px;">
<textarea name=result id=result cols="40" rows="2">比较结果显示!</textarea>
</td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</td>
</tr>
</table>
<%@include file="../bottom.jsp"%>
<SCRIPT type="text/javascript" src="../XTXSAB.js" charset="UTF-8"></SCRIPT>
<SCRIPT LANGUAGE=JAVASCRIPT>
SetAutoLogoutParameter("<%=strCertID%>", demoLogout);
</SCRIPT>
<Script Language="JavaScript">
var strCertID = "<%=strCertID%>";
function pubKeyEncryptCallBack(retObj) {
if (retObj.retVal == "") {
TestForm.cipherData.value = "";
alert("加密数据失败!");
return false;
}
TestForm.cipherData.value = retObj.retVal;
}
function pubicKeyEncData()
{
if (TestForm.plainData.value == "") {
alert("请输入待加密的数据!");
TestForm.plainData.focus();
return ;
}
GetExchCert(strCertID, function(retObj) {
var strEncCert = retObj.retVal;
if (strEncCert == "") {
alert("导出加密证书失败!\n");
return;
}
PubKeyEncrypt(strEncCert, TestForm.plainData.value, pubKeyEncryptCallBack);
});
}
function prikeyDecryptCallBack(retObj) {
var strPlainData = retObj.retVal;
if (strPlainData == "") {
alert("解密数据失败!\n");
TestForm.decryptData.style.color = 'red';
TestForm.decryptData.value = "解密数据失败\n";
} else {
TestForm.decryptData.style.color = 'black';
TestForm.decryptData.value = strPlainData;
}
}
function prikeyDecryptData()
{
PriKeyDecrypt(strCertID, TestForm.cipherData.value, prikeyDecryptCallBack);
}
function CompareData()
{
var o = TestForm.plainData.value;
var t = TestForm.decryptData.value;
if (o == t) {
TestForm.result.style.color = 'black';
TestForm.result.value = "解密后的数据和原文一致!";
} else {
TestForm.result.style.color = 'red';
TestForm.result.value = "解密后的数据和原文不一致!";
}
}
</Script>
</body>
</html>
<%@page contentType="text/html; charset=UTF-8"%>
<%@page contentType="text/html; charset=UTF-8"%>
<%
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.flushBuffer();
//判断session是否失效
String strCertName = (String) session.getAttribute("CertName");
if (strCertName == null || strCertName.equals("")) {
response.sendRedirect("../index.jsp");
}
//获得登陆用户CertID
String strCertID = (String) session.getAttribute("CertID");
%>
<html>
<head>
<title>证书应用演示环境</title>
<style type="text/css">
</style>
<link href="../style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<%@include file="../top.jsp"%>
<table width="957" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td bgcolor="#FEFDFB">
&nbsp;
</td>
</tr>
<tr>
<td width="267" align="left" valign="top">
<%@include file="../form.jsp"%>
</td>
<td align="left" valign="top" bgcolor="#FEFDFB">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
&nbsp;
</td>
<td class="font1">
<img src="../images/jt.gif" width="12" height="12" />
数据P7数字信封功能演示
</td>
</tr>
<tr>
<td height="5"></td>
</tr>
<tr height="2">
<td></td>
<td>
<table width="100%" height="2" border="0" cellpadding="0"
cellspacing="0">
<tr>
<td height="2" bgcolor="#CCCCCC"></td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="10"></td>
</tr>
<tr>
<td>
&nbsp;
</td>
<td align="left" valign="top">
<form method="post" ID="TestForm" action="sign.jsp">
<table width="98%" border="0" align="center" cellpadding="5"
cellspacing="1" class="table1">
<tr>
<td style="font-size:14px;" width="35%">
需要加密的数据:
</td>
<td style="font-size:14px;">
<textarea name=plainData id=plainData cols="40" rows="6" >写入需要加密的数据!</textarea>
</td>
</tr>
<tr>
<td>
<input type="button" value="加密" class="button" style="width:50px;" onClick="EncryptMessage();">
</td>
<td style="font-size:14px;">
<textarea name=envlopeData id=envlopeData cols="40" rows="6">数字信封结果显示!</textarea>
</td>
</tr>
<tr>
<td>
<input type="button" name="B13" value="解密" style="width:50px;" class="button"
width="55" height="28" onClick="DecryptMessage();return false;">
</td>
<td style="font-size:14px;">
<textarea name=decryptData id=decryptData cols="40" rows="6">解密后结果显示!</textarea>
</td>
</tr>
<tr>
<td>
<input type="button" name="B13" value="比较" style="width:50px;" class="button"
width="55" height="28" onClick="CompareData();return false;">
</td>
<td style="font-size:14px;">
<textarea name=compareRes id=compareRes cols="40" rows="2">比较结果显示!</textarea>
</td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</td>
</tr>
</table>
<%@include file="../bottom.jsp"%>
<SCRIPT type="text/javascript" src="../XTXSAB.js"></SCRIPT>
<SCRIPT LANGUAGE=JAVASCRIPT>
SetAutoLogoutParameter("<%=strCertID%>", demoLogout);
</SCRIPT>
<Script Language="JavaScript">
var strCertID = "<%=strCertID%>";
function EncryptMessage()
{
if (TestForm.plainData.value == "") {
alert("请输入待加密的数据!");
TestForm.plainData.focus();
return ;
}
GetExchCert(strCertID, function(retEncCertObj) {
var strEncCert = retEncCertObj.retVal;
if (strEncCert == "") {
alert("导出加密证书失败!\n");
return false;
}
EncodeP7Enveloped(strEncCert, TestForm.plainData.value, function(retCipherObj) {
if (retCipherObj.retVal == ""){
TestForm.envlopeData.value = "";
alert("数字信封加密失败!");
return false;
}
TestForm.envlopeData.value = retCipherObj.retVal;
});
});
}
function DecryptMessage()
{
DecodeP7Enveloped(strCertID, TestForm.envlopeData.value, function(retObj) {
if (retObj.retVal == "") {
alert("数字信封解密失败!\n");
TestForm.decryptData.style.color = 'red';
TestForm.decryptData.value = "数字信封解密失败!\n";
} else {
TestForm.decryptData.style.color = 'black';
TestForm.decryptData.value = retObj.retVal;
}
});
}
function CompareData()
{
var o = TestForm.plainData.value;
var t = TestForm.decryptData.value;
if (o == t) {
TestForm.compareRes.style.color = 'black';
TestForm.compareRes.value = "解密后的数据和原文一致!";
} else {
TestForm.compareRes.style.color = 'red';
TestForm.compareRes.value = "解密后的数据和原文不一致!";
}
}
</Script>
</body>
</html>
<%@page contentType="text/html; charset=UTF-8"%>
<%@page contentType="text/html; charset=UTF-8"%>
<%
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
//判断session是否失效
String strCertName = (String) session.getAttribute("CertName");
if (strCertName == null || strCertName.equals("")) {
response.sendRedirect("../index.jsp");
}
//获得登陆用户CertID
String strCertID = (String) session.getAttribute("CertID");
%>
<html>
<head>
<title>证书应用演示环境</title>
<style type="text/css">
</style>
<link href="../style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<%@include file="../top.jsp"%>
<table width="957" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td bgcolor="#FEFDFB">
&nbsp;
</td>
</tr>
<tr>
<td width="267" align="left" valign="top">
<%@include file="../form.jsp"%>
</td>
<td align="left" valign="top" bgcolor="#FEFDFB">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
&nbsp;
</td>
<td class="font1">
<img src="../images/jt.gif" width="12" height="12" />
数据对称加密功能演示
</td>
</tr>
<tr>
<td height="5"></td>
</tr>
<tr height="2">
<td></td>
<td>
<table width="100%" height="2" border="0" cellpadding="0"
cellspacing="0">
<tr>
<td height="2" bgcolor="#CCCCCC"></td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="10"></td>
</tr>
<tr>
<td>
&nbsp;
</td>
<td align="left" valign="top">
<form method="post" ID="TestForm" action="sign.jsp">
<table width="98%" border="0" align="center" cellpadding="5"
cellspacing="1" class="table1">
<tr>
<td style="font-size:14px;" width="35%">
需要加密的数据:
</td>
<td style="font-size:14px;">
<textarea name=plainData id=plainData cols="40" rows="6" >写入需要加密的数据!</textarea>
</td>
</tr>
<tr>
<td>
<input type="button" value="加密" class="button" style="width:50px;" onClick="EncryptMessage();">
</td>
<td style="font-size:14px;">
<textarea name=cipherData id=cipherData cols="40" rows="6">对称加密结果显示!</textarea>
</td>
</tr>
<tr>
<td>
<input type="button" name="B13" value="解密" style="width:50px;" class="button"
width="55" height="28" onClick="DecryptMessage();return false;">
</td>
<td style="font-size:14px;">
<textarea name=decryptData id=decryptData cols="40" rows="6">解密后结果显示!</textarea>
</td>
</tr>
<tr>
<td>
<input type="button" name="B13" value="比较" style="width:50px;" class="button"
width="55" height="28" onClick="CompareData();return false;">
</td>
<td style="font-size:14px;">
<textarea name=compareRes id=compareRes cols="40" rows="2">比较结果显示!</textarea>
</td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</td>
</tr>
</table>
<%@include file="../bottom.jsp"%>
<SCRIPT type="text/javascript" src="../XTXSAB.js"></SCRIPT>
<SCRIPT LANGUAGE=JAVASCRIPT>
SetAutoLogoutParameter("<%=strCertID%>", demoLogout);
</SCRIPT>
<Script Language="JavaScript">
var strCertID = "<%=strCertID%>";
var strKeyLen = 0;
var strKey = "";
function EncryptMessage()
{
if (TestForm.plainData.value == "") {
alert("请输入待加密的数据!");
TestForm.plainData.focus();
return ;
}
if (strKeyLen == 0) {
strKeyLen = 24;
}
//通过生成随机数接口生成对称密钥
GenerateRandom(strKeyLen, function(retObj) {
strKey = retObj.retVal;
if(strKey == "") {
alert("生成对称密钥失败!")
return;
}
//对称加密数据
EncryptData(strKey, TestForm.plainData.value, function(retCipherObj) {
if (retCipherObj.retVal == ""){
TestForm.cipherData.value = "";
alert("对称加密数据失败!");
return false;
}
TestForm.cipherData.value = retCipherObj.retVal;
});
});
}
function DecryptMessage()
{
DecryptData(strKey, TestForm.cipherData.value, function(retObj) {
if(retObj.retVal == "") {
TestForm.decryptData.style.color = 'red';
TestForm.decryptData.value = "对称解密数据失败";
} else {
TestForm.decryptData.style.color = 'black';
TestForm.decryptData.value = retObj.retVal;
}
});
}
function CompareData()
{
var o = TestForm.plainData.value;
var t = TestForm.decryptData.value;
if (o == t) {
TestForm.compareRes.style.color = 'black';
TestForm.compareRes.value = "解密后的数据和原文一致!";
} else {
TestForm.compareRes.style.color = 'red';
TestForm.compareRes.value = "解密后的数据和原文不一致!";
}
}
</Script>
</body>
</html>
<%
<%
String fpath = request.getContextPath();
%>
<table width="98%" border="0" align="center" cellpadding="0" cellspacing="0" class="boder" style="line-height:30px;">
<tr>
<td width="10">&nbsp;</td>
<td class="font3">其他功能</td>
</tr>
<tr>
<td>&nbsp;</td>
<td align="left">
<img src="<%=fpath%>/images/wb.gif" width="13" height="14" /> 
<A href="<%=fpath%>/other/signData.jsp">数字签名</A>
</td>
</tr>
<tr>
<!--
<td>&nbsp;</td>
<td align="left">
<img src="<%=fpath%>/images/wb.gif" width="13" height="14" /> 
<A href="<%=fpath%>/other/getKeyPic.jsp">获取印章图片</A>
</td>
</tr>
<!--
<tr>
<td>&nbsp;</td>
<td align="left">
<img src="<%=fpath%>/images/wb.gif" width="13" height="14" /> 
<A href="<%=fpath%>/encdec/encData.jsp">非对称加解密</A>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td align="left">
<img src="<%=fpath%>/images/wb.gif" width="13" height="14" /> 
<A href="<%=fpath%>/encdec/p7Envlope.jsp">数字信封加解密</A>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td align="left">
<img src="<%=fpath%>/images/wb.gif" width="13" height="14" /> 
<A href="<%=fpath%>/encdec/symEncData.jsp">数据对称加解密</A>
</td>
</tr>
-->
<tr>
<td>&nbsp;</td>
<td align="left">
<img src="<%=fpath%>/images/wb.gif" width="13" height="14" /> 
<a href="javascript:;" onclick="MyLogout('<%=strCertID%>','<%=fpath%>/logout.jsp')">退出</a>
</td>
</tr>
</table>
<script language=javascript>
function MyLogout(strCertID,fpath) {
//alert(strCertID+fpath);
Logout(strCertID);
window.location.href = fpath;
}
</script>
\ No newline at end of file
BODY { FONT-SIZE: 12px}
BODY { FONT-SIZE: 12px}
TD { FONT-SIZE: 12px}
A.map:link { COLOR: #FF6600; FONT-SIZE: 12px; TEXT-DECORATION: none}
A.map:visited { COLOR: #FF6600; FONT-SIZE: 12px; TEXT-DECORATION: none}
A.map:hover { COLOR: #FFCC00; FONT-SIZE: 12px; TEXT-DECORATION: underline}
A.g:link { COLOR: #666600; FONT-SIZE: 12px; TEXT-DECORATION: none}
A.g:visited { COLOR: #666600; FONT-SIZE: 12px; TEXT-DECORATION: none}
A.g:hover { COLOR: #FF9900; FONT-SIZE: 12px; TEXT-DECORATION: underline}
A:link { COLOR: #0600ee; FONT-SIZE: 12px; TEXT-DECORATION: none}
A:visited { COLOR: #0600ee; FONT-SIZE: 12px; TEXT-DECORATION: none}
A:hover { COLOR: #CC0000; FONT-SIZE: 12px; TEXT-DECORATION: underline}
A.title:link { COLOR: #ffffff; FONT-SIZE: 12px; TEXT-DECORATION: none}
A.title:visited { COLOR: #ffffff; FONT-SIZE: 12px; TEXT-DECORATION: none}
A.title:hover { COLOR: #ffffff; FONT-SIZE: 12px; TEXT-DECORATION: underline}
A.line:link { COLOR: #3300FF; FONT-SIZE: 12px; TEXT-DECORATION: underline}
A.line:visited { COLOR: #3300FF; FONT-SIZE: 12px; TEXT-DECORATION: underline}
A.line:hover { COLOR: #0066FF; FONT-SIZE: 12px; TEXT-DECORATION: underline}
A.line1:link { COLOR: #666666; FONT-SIZE: 12px; TEXT-DECORATION: underline}
A.line1:visited { COLOR: #666666; FONT-SIZE: 12px; TEXT-DECORATION: underline}
A.line1:hover { COLOR: #CC0000; FONT-SIZE: 12px; TEXT-DECORATION: underline}
A.big:link { COLOR: #cc0000; FONT-SIZE: 12px; font-weight: 900; TEXT-DECORATION: underline }
A.big:visited { COLOR: #cc0000; FONT-SIZE: 12px; font-weight: 900; TEXT-DECORATION: underline}
A.big:hover { COLOR: #cc0000; FONT-SIZE: 12px; font-weight: 900; TEXT-DECORATION: underline}
.f1 {BORDER-BOTTOM: 1px inset; BORDER-LEFT: 1px inset; BORDER-RIGHT: 1px inset; BORDER-TOP: 1px inset; height: 14pt; font-size: 12px}
.f2 {BACKGROUND-COLOR: #cccccc; BORDER-BOTTOM: 1px ridge; BORDER-LEFT: #ffffff 1px ridge; BORDER-RIGHT: 1px ridge; BORDER-TOP: #ffffff 1px ridge; height: 14pt; font-size: 12px}
.L { COLOR: #ffffff; FONT-SIZE: 13px; font-weight: bold}
.L14 { LINE-HEIGHT: 140%}
.L15 { LINE-HEIGHT: 150%}
.L16 { LINE-HEIGHT: 160%}
.L17 { LINE-HEIGHT: 170%}
.L18 { LINE-HEIGHT: 180%}
.td2 { color: #CC0000; line-height: 150%}
.zs {border-top: 1px solid #000000; border-right: 1px solid #000000; border-bottom: 1px solid #000000; border-left: 1px solid #000000;}
.l13 { line-height: 120%}
\ No newline at end of file
<%@page contentType="text/html; charset=UTF-8"%>
<%@page contentType="text/html; charset=UTF-8"%>
<%@include file="properties.jsp"%>
<%
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
String strRandom = (String)request.getParameter("strRandom");
String strPath = request.getContextPath();
//获得登陆用户cert
String strClientCert = request.getParameter("UserCert");
String strClientSignedData = request.getParameter("UserSignedData");
String strCertID = request.getParameter("ContainerName");
String strCertIssuer = sed.getCertInfo(strClientCert, 8);
System.out.println("strClientCert:" + strClientCert);
System.out.println("strClientSignedData:" + strClientSignedData);
System.out.println("strCertID:" + strCertID);
System.out.println("strCertIssuer:" + strCertIssuer);
%>
<html>
<head>
<title>证书应用演示环境</title>
<style type="text/css">
</style>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<%@include file="top.jsp"%>
<table width="957" border="0" align="center" cellpadding="0"
cellspacing="0">
<tr>
<td bgcolor="#FEFDFB">
<table width="70%" border="0" align="center" cellpadding="0"
cellspacing="0">
<tr>
<td height="30" colspan="3">
&nbsp;
</td>
</tr>
<tr>
<td width="50" align="right">
<img src="images/cc.gif" width="43" height="62" />
</td>
<td width="20">
&nbsp;
</td>
<td>
<%
System.out.println("strClientCert=" + strClientCert);
System.out.println("strRandom=" + strRandom);
System.out.println("strClientSignedData=" + strClientSignedData);
byte[] signedByte = sed.base64Decode(strClientSignedData);
try {
//证书登陆,第一步,验证客户端签名(涉及方法)
if (sed.verifySignedData(strClientCert, strRandom.getBytes(), signedByte)) {
out.println("<h3>验证客户端签名成功!</h3>");
} else {
out.println("<h3>验证客户端签名错误!</h3>");
return;
}
} catch (Exception e) {
out.println("<p><h3>验证客户端签名错误:" + e.getMessage() + "</h3><p>");
return;
}
try {
//第二步,验证客户端证书
int retValue = sed.validateCert(strClientCert);
if (retValue == 1) {
session.setAttribute("CertID", strCertID); //把certi设置到全局变量,后面签名会用到
String strCertName = "";
try {
strCertName = sed.getCertInfo(strClientCert, 17);
} catch (Exception e) {
out.println("<p><h3>客户端证书验证失败(getCertInfo:17):" + e.getMessage()
+ "</h3><p>");
}
session.setAttribute("CertName", strCertName);
//第三步,获取唯一标识判断用户
String strCertEntityID = "";
try {
//获得登陆用户唯一实体ID,个人证书为身份证号SF+身份证号,单位证书为 JJ+统一社会信用代码,截取掉前面2个字母剩下就是身份证号或统一社会信用代码
strCertEntityID = sed.getCertInfoByOid(strClientCert, "2.16.840.1.113732.2");
strCertEntityID = strCertEntityID.substring(2);
//用这个strCertEntityID绑定用户,以便判断用户是否有权限登陆系统
} catch (Exception e) {
out.println("<p><h3>客户端证书验证失败(getCertInfoByOid):" + e.getMessage()
+ "</h3><p>");
}
out.println("<h3>欢迎您使用本系统!</h3>");
out.println("<h3>主题通用名:");
out.println(strCertName);
out.println("<br/>证书颁发者(颁发者通用名): ");
out.println(strCertIssuer);
out.println("<br/>证书唯一标识:");
out.println(strCertEntityID);
out.println("<br/><font color='red'>(实际集成时,会将唯一标识与数据库比对,判断是否为合法用户)</font>");
out.println("</h3><br/>");
} else {
if (retValue == -1) {
out.println("登录证书的根不被信任");
} else if (retValue == -2) {
out.println("登录证书超过有效期");
} else if (retValue == -3) {
out.println("登录证书为作废证书");
} else if (retValue == -4) {
out.println("登录证书被临时冻结");
}
out.println("</font></h3>");
return;
}
} catch (Exception ex) {
out.println("<p><h3>客户端证书验证失败(-):" + ex.getMessage() + "</h3><p>");
return;
}
%>
</td>
</tr>
<tr>
<td height="30" colspan="3"></td>
</tr>
</table>
</td>
</tr>
<tr>
<td bgcolor="#FEFDFB">
<table width="70%" border="0" align="center" cellpadding="1" cellspacing="1" class="table1">
<tr>
<td>&nbsp;</td>
<td align="left">
<img src="<%=strPath%>/images/wb.gif" width="13" height="14" /> 
<A href="<%=strPath%>/other/signData.jsp">数字签名</A>
</td>
</tr>
<tr>
<td>&nbsp;</td>
<td align="left">
<img src="<%=strPath%>/images/wb.gif" width="13" height="14" /> 
<A href="<%=strPath%>/logout.jsp">退出系统</A>
</td>
</tr>
</table>
</td>
</tr>
<tr>
<td colspan="4" height="50"></td>
</tr>
</table>
<%@include file="bottom.jsp"%>
<SCRIPT type="text/javascript" src="XTXSAB.js" charset="UTF-8"></SCRIPT>
<SCRIPT LANGUAGE=JAVASCRIPT>
//这里实现拔掉key自动退出到登陆页面
SetAutoLogoutParameter("<%=strCertID%>", Logout);
//key插拔回调函数
function Logout() {
alert("你拔掉了ukey!");
window.location.href = "logout.jsp"
}
</SCRIPT>
</body>
</html>
<%@page contentType="text/html; charset=UTF-8"%>
<%@page contentType="text/html; charset=UTF-8"%>
<%
response.setHeader("Pragma","No-cache");
response.setHeader("Cache-Control","no-cache");
response.setDateHeader("Expires", 0);
session.invalidate();
response.sendRedirect("index.jsp");
%>
<%@page contentType="text/html; charset=UTF-8"%>
<%@page contentType="text/html; charset=UTF-8"%>
<%
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.flushBuffer();
//判断session是否失效
String strCertName = (String) session.getAttribute("CertName");
if (strCertName == null || strCertName.equals("")) {
response.sendRedirect("../index.jsp");
}
//获得登陆用户CertID
String strCertID = (String) session.getAttribute("CertID");
%>
<html>
<head>
<title>证书应用演示环境</title>
<style type="text/css">
</style>
<link href="../style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<%@include file="../top.jsp"%>
<table width="957" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td bgcolor="#FEFDFB">
&nbsp;
</td>
</tr>
<tr>
<td width="267" align="left" valign="top">
<%@include file="../form.jsp"%>
</td>
<td align="left" valign="top" bgcolor="#FEFDFB">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
&nbsp;
</td>
<td class="font1">
<img src="../images/jt.gif" width="12" height="12" />
获取Key签章图片
</td>
</tr>
<tr>
<td height="5"></td>
</tr>
<tr>
<td>
&nbsp;
</td>
<td>
<table width="100%" height="2" border="0" cellpadding="0"
cellspacing="0">
<tr>
<td height="2" bgcolor="#CCCCCC"></td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="10"></td>
</tr>
<tr>
<td>
&nbsp;
</td>
<td>
<p align="center">
<font color="#cc3333" size="3"><b>JS脚本自动处理显示证书列表</b> </font>
</p>
<p>
<form method="post" ID="TestForm1">
<table width="98%" border="0" align="center" cellpadding="5"
cellspacing="1" class="table1">
<tr>
<th colspan="2">
<font color="#FF0000" style="font-size:14px;">获取图片后请按照对应格式保存在本地验证是否正确(注意Base64解码)
</th>
</tr>
<tr>
<td style="font-size:14px;" width="35%">
证书列表:
</td>
<td style="font-size:14px;">
<select id="UserList" name="UserList"></select>
</td>
</tr>
<tr>
<td style="font-size:14px;">
<input type="button" value="获取签章图片" class="button" style="width:100px;" onClick="myGetPic();">
</td>
<td style="font-size:14px;">
<textarea name=pic_key id=pic_key cols="40" rows="6">签章图片结果显示!</textarea>
</td>
</tr>
<tr>
<td style="font-size:14px;">
<input type="button" value="印章图片" class="button" style="width:100px;"/>
</td>
<td style="font-size:14px;">
<img id="picImg"/>
</td>
</tr>
</table>
</form>
</p>
</td>
</tr>
</table>
</td>
</tr>
</table>
<%@include file="../bottom.jsp"%>
<SCRIPT type="text/javascript" src="../XTXSAB.js"></SCRIPT>
<Script Language="JavaScript">
SetUserCertList("TestForm1.UserList");
function myGetPic()
{
var strCertID = TestForm1.UserList.value;
GetPic(strCertID, function(retObj) {
if (retObj.retVal == "") {
TestForm1.pic_key.value = "";
alert("获取签章图片失败!\n");
return false;
}
TestForm1.pic_key.value = retObj.retVal;
var picImg = document.getElementById("picImg");
picImg.src = "data:image/gif;base64," + retObj.retVal;
});
}
</Script>
</body>
</html>
<%@page contentType="text/html; charset=UTF-8"%>
<%@page contentType="text/html; charset=UTF-8"%>
<%
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.flushBuffer();
//判断session是否失效
String strCertName = (String) session.getAttribute("CertName");
if (strCertName == null || strCertName.equals("")) {
response.sendRedirect("../index.jsp");
}
//获得登陆用户CertID
String strCertID = (String) session.getAttribute("CertID");
%>
<html>
<head>
<title>证书应用演示环境</title>
<style type="text/css">
</style>
<link href="../style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<%@include file="../top.jsp"%>
<table width="957" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td bgcolor="#FEFDFB">&nbsp;
</td>
</tr>
<tr>
<td width="267" align="left" valign="top">
<%@include file="../form.jsp"%>
</td>
<td align="left" valign="top" bgcolor="#FEFDFB">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
&nbsp;
</td>
<td class="font1">
<img src="../images/jt.gif" width="12" height="12" />
本地数据签名功能演示
</td>
</tr>
<tr>
<td height="5"></td>
</tr>
<tr height="2">
<td></td>
<td>
<table width="100%" height="2" border="0" cellpadding="0"
cellspacing="0">
<tr>
<td height="2" bgcolor="#CCCCCC"></td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="10"></td>
</tr>
<tr>
<td>
&nbsp;
</td>
<td align="left" valign="top">
<form method="post" ID="TestForm">
<table width="98%" border="0" align="center" cellpadding="5"
cellspacing="1" class="table1">
<tr>
<td style="font-size:14px;" width="35%">
需要签名的数据:
</td>
<td style="font-size:14px;">
<textarea name=plainData id=plainData cols="40" rows="6" >写入需要签名的数据!</textarea>
</td>
</tr>
<tr>
<td>
<input type="button" value="签名" class="button" style="width:50px;" onClick="Sign();">
</td>
<td style="font-size:14px;">
<textarea name=signatureData id=signatureData cols="40" rows="6">签名结果显示!</textarea>
</td>
</tr>
<tr>
<td>
<input type="button" name="B13" value="验签" style="width:50px;" class="button"
width="55" height="28" onClick="VerifySign();return false;">
<div align="center">
<font color="#FF0000" style="font-size:14px;">如果修改了明文或签名数据,<br>则验证失败!</font>
</div>
</td>
<td style="font-size:14px;">
<textarea name=verifySign id=verifySign cols="40" rows="6">验证签名结果显示!</textarea>
</td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</td>
</tr>
</table>
<%@include file="../bottom.jsp"%>
<SCRIPT type="text/javascript" src="../XTXSAB.js" charset="UTF-8"></SCRIPT>
<SCRIPT type="text/javascript" src="../DSVSCaller.js" charset="UTF-8"></SCRIPT>
<SCRIPT LANGUAGE=JAVASCRIPT>
//这里实现拔掉key后自动退出系统
SetAutoLogoutParameter("<%=strCertID%>", demoLogout);
</SCRIPT>
<Script Language="JavaScript">
var strCertID = "<%=strCertID%>";
function SignCallBack(retObj) {
if (retObj.retVal == "") {
TestForm.signatureData.value = "";
alert("签名失败!");
return;
}
TestForm.signatureData.value = retObj.retVal;
}
//签名方法
function Sign() {
var plain = TestForm.plainData.value
if (plain == "") {
alert("请输入待签名的数据!");
return ;
}
//对原文进行base64编码之后再签名
Base64Encode(plain,function (retObj){
var base64Plain = retObj.retVal;
if (base64Plain == "") {
alert("Base64编码失败!");
return;
}
//把base64签名后的值赋给表单显示
TestForm.plainData.value = base64Plain;
//对base64编码之后的原文进行签名
SignedData(strCertID, base64Plain, SignCallBack);
});
}
//验证签名
function VerifySign()
{
//获取到签名证书
GetSignCert(strCertID, function(retObj) {
var userCert = retObj.retVal;
var plain = TestForm.plainData.value;
var signedData = TestForm.signatureData.value;
if (userCert == "") {
alert("导出签名证书失败!");
return;
}
//传到后台用服务器验证签名
DSVSCaller.CallDSVS(plain,userCert,signedData,"verifySign");
});
}
</Script>
</body>
</html>
<%@page contentType="text/html; charset=UTF-8"%>
<%@page contentType="text/html; charset=UTF-8"%>
<%
response.setHeader("Pragma", "No-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
response.flushBuffer();
//判断session是否失效
String strCertName = (String) session.getAttribute("CertName");
if (strCertName == null || strCertName.equals("")) {
response.sendRedirect("../index.jsp");
}
//获得登陆用户CertID
String strCertID = (String) session.getAttribute("CertID");
%>
<html>
<head>
<title>证书应用演示环境</title>
<style type="text/css">
</style>
<link href="../style.css" rel="stylesheet" type="text/css" />
</head>
<body>
<%@include file="../top.jsp"%>
<table width="957" border="0" align="center" cellpadding="0" cellspacing="0">
<tr>
<td bgcolor="#FEFDFB">&nbsp;
</td>
</tr>
<tr>
<td width="267" align="left" valign="top">
<%@include file="../form.jsp"%>
</td>
<td align="left" valign="top" bgcolor="#FEFDFB">
<table width="100%" border="0" cellspacing="0" cellpadding="0">
<tr>
<td>
&nbsp;
</td>
<td class="font1">
<img src="../images/jt.gif" width="12" height="12" />
本地数据签名功能演示
</td>
</tr>
<tr>
<td height="5"></td>
</tr>
<tr height="2">
<td></td>
<td>
<table width="100%" height="2" border="0" cellpadding="0"
cellspacing="0">
<tr>
<td height="2" bgcolor="#CCCCCC"></td>
</tr>
</table>
</td>
</tr>
<tr>
<td height="10"></td>
</tr>
<tr>
<td>
&nbsp;
</td>
<td align="left" valign="top">
<form method="post" ID="TestForm">
<table width="98%" border="0" align="center" cellpadding="5"
cellspacing="1" class="table1">
<tr>
<td style="font-size:14px;" width="35%">
需要签名的数据:
</td>
<td style="font-size:14px;">
<textarea name=plainData id=plainData cols="40" rows="6" >写入需要签名的数据!</textarea>
</td>
</tr>
<tr>
<td>
<input type="button" value="签名" class="button" style="width:50px;" onClick="Sign();">
</td>
<td style="font-size:14px;">
<textarea name=signatureData id=signatureData cols="40" rows="6">签名结果显示!</textarea>
</td>
</tr>
<tr>
<td>
<input type="button" name="B13" value="验签" style="width:50px;" class="button"
width="55" height="28" onClick="VerifySign();return false;">
<div align="center">
<font color="#FF0000" style="font-size:14px;">如果修改了明文或签名数据,<br>则验证失败!</font>
</div>
</td>
<td style="font-size:14px;">
<textarea name=verifySign id=verifySign cols="40" rows="6">验证签名结果显示!</textarea>
</td>
</tr
<tr>
<td style="font-size:14px;">
<input type="button" value="印章图片" class="button" style="width:100px;"/>
</td>
<td style="font-size:14px;">
<img id="picImg"/>
</td>
</tr>
</table>
</form>
</td>
</tr>
</table>
</td>
</tr>
</table>
<%@include file="../bottom.jsp"%>
<SCRIPT type="text/javascript" src="../XTXSAB.js" charset="UTF-8"></SCRIPT>
<SCRIPT type="text/javascript" src="../DSVSCaller.js" charset="UTF-8"></SCRIPT>
<SCRIPT LANGUAGE=JAVASCRIPT>
//这里实现拔掉key后自动退出系统
SetAutoLogoutParameter("<%=strCertID%>", demoLogout);
</SCRIPT>
<Script Language="JavaScript">
var strCertID = "<%=strCertID%>";
//function SignCallBack(retObj) {
// if (retObj.retVal == "") {
// TestForm.signatureData.value = "";
// alert("签名失败!");
// return;
// }
// TestForm.signatureData.value = retObj.retVal;
//这里调用
// }
//签名方法
function Sign() {
var plain = TestForm.plainData.value
if (plain == "") {
alert("请输入待签名的数据!");
return ;
}
//第一步,对原文进行base64编码之后再签名
Base64Encode(plain,function (retObj){
//base64后的签名原文
var base64Plain = retObj.retVal;
if (base64Plain == "") {
alert("Base64编码失败!");
return;
}
//把base64签名后的值赋给表单显示,这里是为了演示从而在表单展示,实际集成不需要在表单展示base64原文和签名结果
TestForm.plainData.value = base64Plain;
//第二步,对base64编码之后的原文进行签名
SignedData(strCertID, base64Plain, function(retObj){
//签名后结果
var signedDataRes = retObj.retVal;
if (signedDataRes == "") {
TestForm.signatureData.value = "";
alert("签名失败!");
return;
}
//这里是为了演示从而在表单展示,实际集成不需要在表单展示base64原文和签名结果
TestForm.signatureData.value = signedDataRes;
//第三步,签名成功后,获取用户证书,以便传到后台验证
GetSignCert(strCertID, function(retObj) {
var userCert = retObj.retVal;
var b64plain = base64Plain;
var signedData = signedDataRes;
if (userCert == "") {
alert("导出签名证书失败!");
return;
}
//第四步,传到base64原文、签名值和用户到后台用服务器验证签名
//DSVSCaller.CallDSVS(plain,userCert,signedData,"verifySign");
//以ajax传输为例子
// $.ajax({
// type:"POST",//请求方式
// url:"",//发送请求地址
// dataType:"json",
// data:{b64plain:b64plain,signedData:signedData,userCert:userCert}, //参数
// success:function(data){
// //这里获取到服务器返回的验证结果值
// if (data.res == true){//即验证签名通过并且数据保存到数据库
//第五步,获取印章图片,在页面展示
GetPic(strCertID, function(retObj) {
var pic = retObj.retVal;
if (pic == "") {
alert("获取签章图片失败!\n");
return false;
}
//TestForm1.pic_key.value = pic;
var picImg = document.getElementById("picImg");
picImg.src = "data:image/gif;base64," + pic; //展示印章图片
//第6步,印章展示完成后,需要做其他事情(如果涉及到印章数据的),请必须在这里调用,防止印章数据为空
});
// }
// }
//});
});
});
});
}
//验证签名
function VerifySign()
{
//获取到签名证书
GetSignCert(strCertID, function(retObj) {
var userCert = retObj.retVal;
var plain = TestForm.plainData.value;
var signedData = TestForm.signatureData.value;
if (userCert == "") {
alert("导出签名证书失败!");
return;
}
//传到后台用服务器验证签名
DSVSCaller.CallDSVS(plain,userCert,signedData,"verifySign");
});
}
</Script>
<SCRIPT LANGUAGE=JAVASCRIPT>
//这里实现拔掉key自动退出到登陆页面
SetAutoLogoutParameter("<%=strCertID%>", demoLogout);
//自己写的退出函数
function demoLogout(){
alert("专家拔掉key了,应该退出系统到登陆界面!")
}
</SCRIPT>
</body>
</html>
<%@page import="java.util.*,java.io.FileInputStream"%>
<%@page import="java.util.*,java.io.FileInputStream"%>
<%@page import = "cn.org.bjca.client.security.SecurityEngineDeal"%>
<%
request.setCharacterEncoding("UTF-8");
//指定签名验证服务器配置文件所在路径
SecurityEngineDeal.setProfilePath("C:/DSVSROOT");
SecurityEngineDeal sed = null;
sed = SecurityEngineDeal.getInstance("SVSDefault"); //指定应用名称,测试环境使用这个,生产环境上线时会提供正式的应用名称
%>
\ No newline at end of file
/* CSS Document */
/* CSS Document */
.font1{ font-size:13px;color:#6a6a6a; font-weight:bold;}
.font2{ font-size:13px; color:#999999;}
.font3{ font-size:13px;color:#7b0006; font-weight:bold;}
select{ font-size:13px;color:#6a6a6a; font-weight:bold;}
input{font-size:13px;color:#6a6a6a; font-weight:bold;}
.tableboder{ border:1px solid #CCCCCC }
.table1{ background:#cccccc; line-height:25px;text-align:center;}
.table1 tr{ background:#FFFFFF;}
.boder{ border:
border: 2px solid #c6c6c6;
border: 2px solid #c6c6c6;
background-color: #FFFFFF;
}
.button{
font-family:Arial, Helvetica, sans-serif;
font-size:13px;
font-weight:bold;
color: #FFFFFF;
text-align:center;
border: 0px solid #c02947;
background-image: url(images/buttonn.gif);
height:24px;
}
\ No newline at end of file
<%
<%
String tpath = request.getContextPath();
%>
<table width="957" border="0" align="center" cellpadding="0"
cellspacing="0">
<tr>
<td height="60">
<img src="<%=tpath%>/images/logo.gif" width="245" height="38" />
</td>
</tr>
<tr>
<td>
<img src="<%=tpath%>/images/banner.gif" width="957" height="68" />
</td>
</tr>
</table>
<script language=javascript>
function demoLogout() {
window.location.href = '<%=tpath%>/logout.jsp';
}
</script>
\ No newline at end of file
##############################################
##############################################
##语法说明:
#1 以 #开头的行为注释行;
#2 每行只能有一条语句;
#3 每行最多字符数目256个,包括空格;
#4 可以有任意多的空行;
#5 以[开始和以]结尾表示开始一个段落
#6 属于同一个段的内容必须放在同一个段内;
#7 =号前的为项目名称,其后为项目的值
#8 所能支持的段名与项目名称为内部定义好的,不能随意扩展
##################################################
#服务器个数
serverNum=1
#高院正式使用生产环境地址
address1=147.2.3.88
port1=8000
#最小链接数
minConnNum=20
#最大链接数
maxConnNum=50
#超时时间(毫秒)
timeout=5000
#是否开启DEBUG
isDebug=false
#客户端默认字符集
encoding=GBK
#连接模式(1为短连接,0为长连接)
connectionMode=1
#连接超时时间,可选
connectionTimeout=3000
\ No newline at end of file
/*
* 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.
*/
/* reset */
html, body, div, span, object, iframe, h1, h2, h3, h4, h5, h6, p, blockquote, pre, abbr, address, cite, code, del, dfn, em, img, ins, kbd, q, samp, small, strong, sub, sup, var, b, i, dl, dt, dd, ol, ul, li, fieldset, form, label, legend, table, caption, tbody, tfoot, thead, tr, th, td, article, aside, canvas, details, figcaption, figure, footer, header, hgroup, menu, nav, section, summary, time, mark, audio, video { margin: 0; padding: 0; border: 0; outline: 0; font-size: 100%; vertical-align: baseline; background: transparent; }
body { line-height: 1; }
article, aside, details, figcaption, figure, footer, header, hgroup, menu, nav, section { display: block; }
nav ul { list-style: none; }
blockquote, q { quotes: none; }
blockquote:before, blockquote:after, q:before, q:after { content: ''; content: none; }
a { margin: 0; padding: 0; font-size: 100%; vertical-align: baseline; background: transparent; }
/* change colours to suit your needs */
ins { background-color: #ff9; color: #000; text-decoration: none; }
/* change colours to suit your needs */
mark { background-color: #ff9; color: #000; font-style: italic; font-weight: bold; }
del { text-decoration: line-through; }
abbr[title], dfn[title] { border-bottom: 1px dotted; cursor: help; }
table { border-collapse: collapse; border-spacing: 0; }
/* change border colour to suit your needs */
hr { display: block; height: 1px; border: 0; border-top: 1px solid #cccccc; margin: 1em 0; padding: 0; }
input, select { vertical-align: middle; }
/* general page */
body { font-family: Verdana, sans-serif; font-size: 11px; line-height: 1.4em; }
#cas { background: #eee; }
#cas .flc-screenNavigator-view-container { width: 95%; margin: 0 auto; }
#cas .flc-screenNavigator-view-container #header, #cas .flc-screenNavigator-view-container #content { background: #fff; -webkit-box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.1); box-shadow: 0px 0px 20px 0px rgba(0, 0, 0, 0.1); }
#cas .flc-screenNavigator-view-container #content { -webkit-border-bottom-right-radius: 4px; -webkit-border-bottom-left-radius: 4px; -moz-border-radius-bottomright: 4px; -moz-border-radius-bottomleft: 4px; border-bottom-right-radius: 4px; border-bottom-left-radius: 4px; }
@media only screen and (max-width: 960px) { #cas .flc-screenNavigator-view-container { width: 100%; }
#cas .flc-screenNavigator-view-container #content { -webkit-border-bottom-right-radius: 0px; -webkit-border-bottom-left-radius: 0px; -moz-border-radius-bottomright: 0px; -moz-border-radius-bottomleft: 0px; border-bottom-right-radius: 0px; border-bottom-left-radius: 0px; } }
/* header */
#cas #header { padding-top: 10px; }
#cas #header #company-name { width: 118px; height: 31px; text-indent: -999em; background: url(../images/ja-sig-logo.gif) no-repeat; margin: 0 0 10px 10px; }
#cas #header #app-name { background: #210F7A; color: white; padding: 1.4em 1.4em; font-size: 2em; font-weight: normal; }
/* content */
#cas #content { padding: 10px; overflow: hidden; }
#cas #content #msg { padding: 20px; margin-bottom: 10px; }
#cas #content #msg h2 { font-size: 1.4em; margin-bottom: 0.5em; }
#cas #content #msg.errors { border: 1px dotted #BB0000; color: #BB0000; padding-left: 100px; background: url(../images/error.gif) no-repeat 20px center; }
#cas #content #msg.success { border: 1px dotted #390; color: #390; padding-left: 100px; background: url(../images/confirm.gif) no-repeat 20px center; }
#cas #content #msg.info { border: 1px dotted #008; color: #008; padding-left: 100px; background: url(../images/info.gif) no-repeat 20px center; }
#cas #content #login { width: 320px; float: left; margin-right: 20px; }
#cas #content #login #fm1 { padding: 20px; background: #eee; -webkit-border-radius: 5px; -moz-border-radius: 5px; border-radius: 5px; }
#cas #content #login #fm1 h2 { font-size: 1.4em; font-weight: normal; padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px solid #DDDDDD; }
#cas #content #login #fm1 .row { margin-bottom: 10px; }
#cas #content #login #fm1 .row .fl-label { display: block; color: #777777; }
#cas #content #login #fm1 .row input[type=text], #cas #content #login #fm1 .row input[type=password] { padding: 6px; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; border: 1px solid #DDDDDD; background: #FFFFDD; }
#cas #content #login #fm1 .row.check { padding-bottom: 10px; margin-bottom: 10px; border-bottom: 1px solid #DDDDDD; color: #777; font-size: 11px; }
#cas #content #login #fm1 .row .btn-submit { border-width: 2px; padding: 3px; margin-right: 4px; }
#cas #content #login #fm1 .row .btn-reset { border: 0; background: none; color: #777; text-transform: lowercase; border-left: 1px solid #ddd; }
#cas #content #login #fm1 .row .btn-submit:hover, #cas #content #login #fm1 .row .btn-reset:hover { cursor: pointer; }
#cas #content #sidebar { width: auto; }
#cas #content #sidebar .sidebar-content { padding-left: 20px; }
#cas #content #sidebar .sidebar-content p { margin-bottom: 1.4em; }
#cas #content #sidebar .sidebar-content #list-languages ul { list-style: none; }
#cas #content #sidebar .sidebar-content #list-languages ul li { display: inline-block; padding: 0px 10px; border-right: 1px solid #e2e2e2; }
#cas #content #sidebar .sidebar-content #list-languages ul li:last-child { border: 0; line-height: 1.4em; }
/* footer */
#cas #footer { color: #999; margin: 20px 0; }
/* < 960 */
@media only screen and (max-width: 960px) { #cas #footer { padding-left: 10px; } }
/* < 799 */
@media only screen and (max-width: 799px) { #cas #header #app-name { font-size: 1em; }
#cas #content #login { float: none; width: 100%; }
#cas #content #login #fm1 .row .fl-label { margin-left: -10px; }
#cas #content #login #fm1 .row input[type=text], #cas #content #login #fm1 .row input[type=password] { width: 100%; margin-left: -10px; padding: 10px; }
#cas #content #login #fm1 .row .btn-submit { outline: none; -webkit-appearance: none; -webkit-border-radius: 0; border: 0; background: #210F7A; color: white; font-weight: bold; width: 100%; padding: 10px 20px; -webkit-border-radius: 3px; -moz-border-radius: 3px; border-radius: 3px; }
#cas #content #login #fm1 .row .btn-reset { display: none; }
#cas #content #sidebar { margin-top: 20px; }
#cas #content #sidebar .sidebar-content { padding: 0; } }
/*
* 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.
*/
/***************************************/
/* general styles */
html {
background: -webkit-gradient(linear, left top, right top,
from(#c5ccd3),
to(#cfd5dd),
color-stop(0.80, #c5ccd3),
color-stop(0.80, #cfd5dd));
}
.fl-theme-uportal .fl-bevel-black {
text-shadow: rgba(0,0,0,0.35) 0px -1px 0px;
}
.fl-theme-uportal .fl-bevel-white {
text-shadow: rgba(255,255,255,1) 0px 1px 0px;
}
.fl-theme-uportal a {
-webkit-touch-callout:none; /* prevents iphone popup menu to copy / follow / bookmark a particular link */
-webkit-tap-highlight-color: rgba(0,0,0,0);
text-decoration:none;
color:#000;
}
/***************************************/
/* Navigation Bar */
body::before {
border-top-color:#ccd6e2;
border-bottom-color:#000;
background-image: -webkit-gradient(linear, left top, left bottom,
from(#B0BCCD),
color-stop(0.5, #889BB3),
color-stop(0.50, #6D84A2),
to(#6D84A2)
);
}
.fl-theme-uportal .fl-navbar {
color:#fff;
text-shadow: rgba(0,0,0,0.5) 0px -1px 0px;
}
.fl-theme-uportal .fl-navbar h1 {
color:#fff;
}
.fl-theme-uportal .fl-navbar a {
color: #fff;
}
.fl-theme-uportal .fl-navbar [class*=fl-button] {
background-image: -webkit-gradient(linear, left top, left bottom,
from(#9aafca),
color-stop(0.5, #6d8cb3),
color-stop(0.50, #4b6b90),
to(#4b6b90)
);
-webkit-border-image:none;
}
.fl-theme-uportal .fl-navbar [class*=fl-button]:active {
background-image: -webkit-gradient(linear, left top, left bottom,
from(rgba(149, 184, 239,1)),
to(rgba(35,109,229,1)),
color-stop(0.5, rgba(149, 184, 239,1)),
color-stop(0.50, rgba(75,148,244,1))
);
}
.fl-theme-uportal .fl-navbar .fl-backButton {
/* See mobile layout for details */
-webkit-border-image: url(images/iphone/navbar_back_button_insetShadow.png) 0 15 stretch;
-webkit-mask-box-image: url(images/iphone/backbutton_mask.png) 0 15 stretch;
}
.fl-theme-uportal .fl-navbar .fl-button-inner {
-webkit-border-image: url(images/iphone/navbar_normal_button_insetShadow.png) 5 5 5 5 stretch;
}
/***************************************/
/* iPhone general purpose gel buttons */
/* effect is applied anywhere but the navbar, which has its own button look */
.fl-theme-uportal .fl-button {
text-decoration:none;
font-weight:bold;
-webkit-border-image: url(images/iphone/button_bg_insetShadow.png) 10 stretch;
}
.fl-theme-uportal .fl-button.fl-bevel-white {
color:#333333;
}
.fl-theme-uportal .fl-button.fl-bevel-black {
color:#FFFFFF;
}
.fl-theme-uportal .fl-button-white {
background-image: -webkit-gradient(linear, left top, left bottom,
from(rgba(240,240,240,0.25)),
to(rgba(220,220,220,0.75)),
color-stop(0.5, rgba(240,240,240,1)),
color-stop(0.50, rgba(200,200,200,0.8))
);
}
.fl-theme-uportal .fl-button-black {
background-image: -webkit-gradient(linear, left top, left bottom,
from(rgba(106,106,106,0.25)),
to(rgba(00,00,00,0.75)),
color-stop(0.5, rgba(130,130,130,1)),
color-stop(0.50, rgba(75,75,75,0.8))
);
}
.fl-theme-uportal .fl-button-green {
background-image: -webkit-gradient(linear, left top, left bottom,
from(rgba(120,190,130,0.2)),
to(rgba(50,170,60,0.75)),
color-stop(0.5, rgba(120,190,130,1)),
color-stop(0.50, rgba(0,150,10,0.8))
);
}
.fl-theme-uportal .fl-button-blue {
background-image: -webkit-gradient(linear, left top, left bottom,
from(rgba(149, 184, 239,0.2)),
to(rgba(35,109,229,0.75)),
color-stop(0.5, rgba(149, 184, 239,1)),
color-stop(0.50, rgba(75,148,244,0.8))
);
}
/***************************************/
/* iPhone tabs 1: small general purpose content dividers */
.fl-theme-uportal .fl-tabs li {
background-image: -webkit-gradient(linear, left top, left bottom,
from(#9aafca),
color-stop(0.5, #6d8cb3),
color-stop(0.50, #4b6b90),
to(#4b6b90)
);
-webkit-border-image: url(images/iphone/navbar_normal_button_insetShadow.png) 5 5 5 5 stretch;
-webkit-border-left-image: none;
-webkit-background-origin: border;
-webkit-background-clip: border;
}
.fl-theme-uportal .fl-tabs .fl-tabs-active {
background-image: -webkit-gradient(linear, left top, left bottom,
from(rgba(149, 184, 239,1)),
to(rgba(35,109,229,1)),
color-stop(0.5, rgba(149, 184, 239,1)),
color-stop(0.50, rgba(75,148,244,1))
);
}
.fl-theme-uportal .fl-tabs li a,
.fl-theme-uportal .fl-tabs .fl-tabs-active a {
color:#fff;
border-right-color:rgba(255,255,255,0.35);
border-left-color:rgba(0,0,0,0.35);
}
/*************************************************/
/* iPhone list menu styles: Ordered lists, Unordererd lists, Thumbnail lists, Icon lists, Definition lists */
/*************************************************/
/* Default list system setup */
.fl-theme-uportal .fl-listmenu li a {
-webkit-tap-highlight-color: -webkit-gradient(linear, left top, left bottom, from(#4a94f4), to(#236de5));
background:#fff url(images/iphone/listmenu_arrow.png) no-repeat right 5px;
}
.fl-theme-uportal [class*=fl-list] > li {
color: #000;
border-color: rgb(169,173,176);
background-color:#fff;
}
/* A simulation for a:active on the device, requires JS */
.fl-theme-uportal [class*=fl-list]:not(.fl-list) a:active,
.fl-theme-uportal [class*=fl-list] .fl-link-hilight {
color: #fff;
background: url(images/iphone/listmenu_arrow.png) no-repeat right -25px,
-webkit-gradient(linear, left top, left bottom, from(#4a94f4), to(#236de5));
}
.fl-theme-uportal [class*=fl-list] .fl-link-loading {
color: #fff !important;
background: url(images/iphone/listmenu_loader.gif) no-repeat 97% center,
-webkit-gradient(linear, left top, left bottom, from(#4a94f4), to(#236de5));
}
.fl-theme-uportal [class*=fl-list]:not(.fl-list) a:active,
.fl-theme-uportal [class*=fl-list] a:active .fl-link-secondary,
.fl-theme-uportal [class*=fl-list] a:active .fl-link-summary,
.fl-theme-uportal [class*=fl-list] .fl-link-loading * {
color: #fff !important;
}
/* secondary link info behaviour */
.fl-theme-uportal [class*=fl-list] > li .fl-link-secondary {
color: rgb(50, 79, 133);
}
/* summary link info ehaviour */
.fl-theme-uportal [class*=fl-list] > li .fl-link-summary {
color:#999;
}
.fl-theme-uportal .fl-list a {
color:#4a94f4;
}
/***************************************/
/* instructional text (usually embossed too)*/
.fl-theme-uportal .fl-note {
color:#4C566C;
}
/****************************/
/* Collapsing and expanding panels */
.fl-theme-uportal .fl-panel-autoHeading > *:first-child {
color:#fff;
background: -webkit-gradient(linear, left top, left bottom, from(#999), to(#000));
}
.fl-theme-uportal .fl-panel-autoHeading > *:first-child:focus {
color:#000;
background: -webkit-gradient(linear, left top, left bottom, from(#FFF), to(#CCC));
}
/****************************/
/* Gloss tint for glossy icons/thumbnails */
.fl-theme-uportal .fl-list-glossy > li a::before {
background-image: -webkit-gradient(radial, 50% -15%, 10, 50% -50%, 45, from(rgba(255,255,255,1)), to(rgba(255,255,255,0)), color-stop(90%, rgba(255,255,255,.65)));
}
/*
------------------------------------
Overrides to jqueryui css.
------------------------------------
*/
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button,
.ui-widget {font-size: 1em; font-family:arial,helvetica,clean,sans-serif;}
.ui-tabs .ui-tabs-nav li a {
font-size: 0.8em;
padding:0.2em 0.5em;
}
.ui-tabs .ui-tabs-nav {
padding:0.2em 0.1em 0;
}
/* jQuery tooltip */
#tooltip {background-color: #fffbbf; color: #344461; border: thin solid #b1c6f2;}
/*
*/
#portalWelcome { text-align: right; padding-right: 10px; }
.portlet-content-container { background-color: #fff; padding: 5px; margin: 5px; }
/* Fluid pager component styles */
.fl-theme-uportal .fl-pager ul.fl-pager-ui {text-align:right}
.fl-theme-uportal .fl-pager .fl-pager-ui li {list-style-type:none; display:inline; padding-left:5px}
.fl-theme-uportal .fl-pager .fl-pager-ui a.fl-pager-disabled,
.fl-theme-uportal .fl-pager .fl-pager-ui .fl-pager-disabled a { color: #777777; border: 0; text-decoration: none; cursor: default; }
.fl-theme-uportal .fl-pager .fl-pager-ui a.fl-pager-currentPage,
.fl-theme-uportal .fl-pager .fl-pager-ui .fl-pager-currentPage a { color: #000000; border: 0; text-decoration: none; cursor: default;}
.fl-theme-uportal a { color:#4b6b90; }
.up-mobile-navigation-container a { color:#000; }
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
/*
* 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.
*/
#header, #content, #footer, .clearfix, #student .row, #student .col {zoom:1;} /* needs to be seen by IE7 to trigger hasLayout */
/* FOOTER --------------------------------- */
#footer {padding-bottom:1em;}
/* lt IE6 */
* html #cas #login .btn-submit {background:#ffd;}
* html #cas #login .btn-row {top:5px;}
* html #sidebar {display:inline;} /* double margin on float bug */
* html input.btn-submit {padding:2px .25em; width:0; overflow:visible;} /* extra width fix */
\ No newline at end of file
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
This source diff could not be displayed because it is too large. You can view the blob instead.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment