站点更新:2018-03-27 15:37:33
This commit is contained in:
commit
97257044a4
6
.idea/emacs.xml
Normal file
6
.idea/emacs.xml
Normal file
@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="EmacsSettings">
|
||||
<option name="emacsPath" value="/usr/bin/emacs" />
|
||||
</component>
|
||||
</project>
|
9
.idea/jwt.iml
Normal file
9
.idea/jwt.iml
Normal file
@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<module type="WEB_MODULE" version="4">
|
||||
<component name="Go" enabled="true" />
|
||||
<component name="NewModuleRootManager">
|
||||
<content url="file://$MODULE_DIR$" />
|
||||
<orderEntry type="inheritedJdk" />
|
||||
<orderEntry type="sourceFolder" forTests="false" />
|
||||
</component>
|
||||
</module>
|
8
.idea/modules.xml
Normal file
8
.idea/modules.xml
Normal file
@ -0,0 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectModuleManager">
|
||||
<modules>
|
||||
<module fileurl="file://$PROJECT_DIR$/.idea/jwt.iml" filepath="$PROJECT_DIR$/.idea/jwt.iml" />
|
||||
</modules>
|
||||
</component>
|
||||
</project>
|
53
.idea/watcherTasks.xml
Normal file
53
.idea/watcherTasks.xml
Normal file
@ -0,0 +1,53 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ProjectTasksOptions">
|
||||
<TaskOptions isEnabled="true">
|
||||
<option name="arguments" value="fmt $FilePath$" />
|
||||
<option name="checkSyntaxErrors" value="true" />
|
||||
<option name="description" />
|
||||
<option name="exitCodeBehavior" value="ERROR" />
|
||||
<option name="fileExtension" value="go" />
|
||||
<option name="immediateSync" value="false" />
|
||||
<option name="name" value="go fmt" />
|
||||
<option name="output" value="$FilePath$" />
|
||||
<option name="outputFilters">
|
||||
<array />
|
||||
</option>
|
||||
<option name="outputFromStdout" value="false" />
|
||||
<option name="program" value="$GoExecPath$" />
|
||||
<option name="runOnExternalChanges" value="false" />
|
||||
<option name="scopeName" value="Project Files" />
|
||||
<option name="trackOnlyRoot" value="true" />
|
||||
<option name="workingDir" value="" />
|
||||
<envs>
|
||||
<env name="GOROOT" value="$GOROOT$" />
|
||||
<env name="GOPATH" value="$GOPATH$" />
|
||||
<env name="PATH" value="$GoBinDirs$" />
|
||||
</envs>
|
||||
</TaskOptions>
|
||||
<TaskOptions isEnabled="true">
|
||||
<option name="arguments" value="-w $FilePath$" />
|
||||
<option name="checkSyntaxErrors" value="true" />
|
||||
<option name="description" />
|
||||
<option name="exitCodeBehavior" value="ERROR" />
|
||||
<option name="fileExtension" value="go" />
|
||||
<option name="immediateSync" value="false" />
|
||||
<option name="name" value="goimports" />
|
||||
<option name="output" value="$FilePath$" />
|
||||
<option name="outputFilters">
|
||||
<array />
|
||||
</option>
|
||||
<option name="outputFromStdout" value="false" />
|
||||
<option name="program" value="goimports" />
|
||||
<option name="runOnExternalChanges" value="false" />
|
||||
<option name="scopeName" value="Project Files" />
|
||||
<option name="trackOnlyRoot" value="true" />
|
||||
<option name="workingDir" value="" />
|
||||
<envs>
|
||||
<env name="GOROOT" value="$GOROOT$" />
|
||||
<env name="GOPATH" value="$GOPATH$" />
|
||||
<env name="PATH" value="$GoBinDirs$" />
|
||||
</envs>
|
||||
</TaskOptions>
|
||||
</component>
|
||||
</project>
|
302
.idea/workspace.xml
Normal file
302
.idea/workspace.xml
Normal file
@ -0,0 +1,302 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="ChangeListManager">
|
||||
<list default="true" id="847c5949-378a-4c01-9318-d1db88c22ef9" name="Default" comment="" />
|
||||
<option name="EXCLUDED_CONVERTED_TO_IGNORED" value="true" />
|
||||
<option name="TRACKING_ENABLED" value="true" />
|
||||
<option name="SHOW_DIALOG" value="false" />
|
||||
<option name="HIGHLIGHT_CONFLICTS" value="true" />
|
||||
<option name="HIGHLIGHT_NON_ACTIVE_CHANGELIST" value="false" />
|
||||
<option name="LAST_RESOLUTION" value="IGNORE" />
|
||||
</component>
|
||||
<component name="FileEditorManager">
|
||||
<leaf>
|
||||
<file leaf-file-name="showtoken.go" pinned="false" current-in-tab="false">
|
||||
<entry file="file://$PROJECT_DIR$/token/showtoken.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="527">
|
||||
<caret line="39" column="24" lean-forward="true" selection-start-line="39" selection-start-column="24" selection-end-line="39" selection-end-column="24" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
<file leaf-file-name="token.go" pinned="false" current-in-tab="true">
|
||||
<entry file="file://$PROJECT_DIR$/token/token.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="251">
|
||||
<caret line="38" column="5" lean-forward="false" selection-start-line="38" selection-start-column="5" selection-end-line="38" selection-end-column="5" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</file>
|
||||
</leaf>
|
||||
</component>
|
||||
<component name="GOROOT" path="/usr/local/opt/go/libexec" />
|
||||
<component name="IdeDocumentHistory">
|
||||
<option name="CHANGED_PATHS">
|
||||
<list>
|
||||
<option value="$PROJECT_DIR$/cmd/verify.go" />
|
||||
<option value="$PROJECT_DIR$/cmd/show.go" />
|
||||
<option value="$PROJECT_DIR$/token/signtoken.go" />
|
||||
<option value="$PROJECT_DIR$/cmd/sign.go" />
|
||||
<option value="$PROJECT_DIR$/token/token.go" />
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="JsBuildToolGruntFileManager" detection-done="true" sorting="DEFINITION_ORDER" />
|
||||
<component name="JsBuildToolPackageJson" detection-done="true" sorting="DEFINITION_ORDER" />
|
||||
<component name="JsGulpfileManager">
|
||||
<detection-done>true</detection-done>
|
||||
<sorting>DEFINITION_ORDER</sorting>
|
||||
</component>
|
||||
<component name="ProjectFrameBounds" extendedState="6">
|
||||
<option name="x" value="1920" />
|
||||
<option name="y" value="23" />
|
||||
<option name="width" value="1440" />
|
||||
<option name="height" value="877" />
|
||||
</component>
|
||||
<component name="ProjectView">
|
||||
<navigator currentView="ProjectPane" proportions="" version="1">
|
||||
<flattenPackages />
|
||||
<showMembers />
|
||||
<showModules />
|
||||
<showLibraryContents />
|
||||
<hideEmptyPackages />
|
||||
<abbreviatePackageNames />
|
||||
<autoscrollToSource />
|
||||
<autoscrollFromSource />
|
||||
<sortByType />
|
||||
<manualOrder />
|
||||
<foldersAlwaysOnTop value="true" />
|
||||
</navigator>
|
||||
<panes>
|
||||
<pane id="Scratches" />
|
||||
<pane id="ProjectPane">
|
||||
<subPane>
|
||||
<expand>
|
||||
<path>
|
||||
<item name="jwt" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="jwt" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="jwt" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="jwt" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="cmd" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
<path>
|
||||
<item name="jwt" type="b2602c69:ProjectViewProjectNode" />
|
||||
<item name="jwt" type="462c0819:PsiDirectoryNode" />
|
||||
<item name="token" type="462c0819:PsiDirectoryNode" />
|
||||
</path>
|
||||
</expand>
|
||||
<select />
|
||||
</subPane>
|
||||
</pane>
|
||||
<pane id="Scope" />
|
||||
</panes>
|
||||
</component>
|
||||
<component name="PropertiesComponent">
|
||||
<property name="nodejs_interpreter_path.stuck_in_default_project" value="undefined stuck path" />
|
||||
<property name="last_opened_file_path" value="$PROJECT_DIR$" />
|
||||
<property name="go.sdk.automatically.set" value="true" />
|
||||
<property name="settings.editor.selected.configurable" value="watcher.settings" />
|
||||
</component>
|
||||
<component name="RunDashboard">
|
||||
<option name="ruleStates">
|
||||
<list>
|
||||
<RuleState>
|
||||
<option name="name" value="ConfigurationTypeDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
<RuleState>
|
||||
<option name="name" value="StatusDashboardGroupingRule" />
|
||||
</RuleState>
|
||||
</list>
|
||||
</option>
|
||||
</component>
|
||||
<component name="RunManager">
|
||||
<configuration name="go build main.go" type="GoApplicationRunConfiguration" factoryName="Go Application" temporary="true">
|
||||
<module name="jwt" />
|
||||
<working_directory value="$PROJECT_DIR$/" />
|
||||
<go_parameters value="-i" />
|
||||
<parameters value="show -t -" />
|
||||
<kind value="FILE" />
|
||||
<filePath value="$PROJECT_DIR$/main.go" />
|
||||
<package value="github.com/ehlxr/jwt" />
|
||||
<directory value="$PROJECT_DIR$/" />
|
||||
</configuration>
|
||||
<recent_temporary>
|
||||
<list size="1">
|
||||
<item index="0" class="java.lang.String" itemvalue="Go Build.go build main.go" />
|
||||
</list>
|
||||
</recent_temporary>
|
||||
</component>
|
||||
<component name="ShelveChangesManager" show_recycled="false">
|
||||
<option name="remove_strategy" value="false" />
|
||||
</component>
|
||||
<component name="ToolWindowManager">
|
||||
<frame x="1920" y="23" width="1440" height="877" extended-state="6" />
|
||||
<editor active="true" />
|
||||
<layout>
|
||||
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32992327" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" show_stripe_button="true" weight="0.17381974" sideWeight="0.5" order="0" side_tool="false" content_ui="combo" />
|
||||
<window_info id="Hierarchy" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.24964234" sideWeight="0.5" order="2" side_tool="false" content_ui="combo" />
|
||||
<window_info id="Docker" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.32992327" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
|
||||
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.39897698" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
|
||||
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" show_stripe_button="true" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
|
||||
</layout>
|
||||
</component>
|
||||
<component name="TypeScriptGeneratedFilesManager">
|
||||
<option name="version" value="1" />
|
||||
</component>
|
||||
<component name="VcsContentAnnotationSettings">
|
||||
<option name="myLimit" value="2678400000" />
|
||||
</component>
|
||||
<component name="XDebuggerManager">
|
||||
<breakpoint-manager>
|
||||
<breakpoints>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/token/token.go</url>
|
||||
<line>45</line>
|
||||
<properties />
|
||||
<option name="timeStamp" value="4" />
|
||||
</line-breakpoint>
|
||||
<line-breakpoint enabled="true" type="DlvLineBreakpoint">
|
||||
<url>file://$PROJECT_DIR$/token/token.go</url>
|
||||
<line>39</line>
|
||||
<properties />
|
||||
<option name="timeStamp" value="7" />
|
||||
</line-breakpoint>
|
||||
</breakpoints>
|
||||
<option name="time" value="8" />
|
||||
</breakpoint-manager>
|
||||
<watches-manager />
|
||||
</component>
|
||||
<component name="editorHistoryManager">
|
||||
<entry file="file://$PROJECT_DIR$/main.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="247">
|
||||
<caret line="13" column="20" lean-forward="false" selection-start-line="13" selection-start-column="20" selection-end-line="13" selection-end-column="20" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/cmd/root.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="317">
|
||||
<caret line="47" column="18" lean-forward="true" selection-start-line="46" selection-start-column="8" selection-end-line="47" selection-end-column="18" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/cmd/show.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="129">
|
||||
<caret line="39" column="22" lean-forward="true" selection-start-line="39" selection-start-column="22" selection-end-line="39" selection-end-column="22" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/util/tokenutil.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="185">
|
||||
<caret line="34" column="5" lean-forward="false" selection-start-line="34" selection-start-column="5" selection-end-line="34" selection-end-column="5" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/../../spf13/pflag/string.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="171">
|
||||
<caret line="9" column="0" lean-forward="true" selection-start-line="9" selection-start-column="0" selection-end-line="9" selection-end-column="0" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/../../spf13/pflag/uint64.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="95">
|
||||
<caret line="5" column="5" lean-forward="false" selection-start-line="5" selection-start-column="5" selection-end-line="5" selection-end-column="5" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/../../spf13/pflag/duration.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="95">
|
||||
<caret line="7" column="5" lean-forward="false" selection-start-line="7" selection-start-column="5" selection-end-line="7" selection-end-column="5" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/../../spf13/pflag/flag.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="142">
|
||||
<caret line="174" column="8" lean-forward="false" selection-start-line="174" selection-start-column="8" selection-end-line="174" selection-end-column="8" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/../../spf13/pflag/flag_test.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="379">
|
||||
<caret line="1072" column="14" lean-forward="true" selection-start-line="1072" selection-start-column="14" selection-end-line="1072" selection-end-column="14" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/token/signtoken.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="583">
|
||||
<caret line="119" column="0" lean-forward="false" selection-start-line="119" selection-start-column="0" selection-end-line="119" selection-end-column="0" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/cmd/verify.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="613">
|
||||
<caret line="53" column="27" lean-forward="false" selection-start-line="53" selection-start-column="22" selection-end-line="53" selection-end-column="27" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/cmd/sign.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="602">
|
||||
<caret line="51" column="48" lean-forward="false" selection-start-line="51" selection-start-column="48" selection-end-line="51" selection-end-column="48" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/token/showtoken.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="527">
|
||||
<caret line="39" column="24" lean-forward="true" selection-start-line="39" selection-start-column="24" selection-end-line="39" selection-end-column="24" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
<entry file="file://$PROJECT_DIR$/token/token.go">
|
||||
<provider selected="true" editor-type-id="text-editor">
|
||||
<state relative-caret-position="251">
|
||||
<caret line="38" column="5" lean-forward="false" selection-start-line="38" selection-start-column="5" selection-end-line="38" selection-end-column="5" />
|
||||
<folding />
|
||||
</state>
|
||||
</provider>
|
||||
</entry>
|
||||
</component>
|
||||
</project>
|
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright © 2018 ehlxr <ehlxr.me@gmail.com>
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
84
cmd/root.go
Normal file
84
cmd/root.go
Normal file
@ -0,0 +1,84 @@
|
||||
// Copyright © 2018 ehlxr <ehlxr.me@gmail.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
homedir "github.com/mitchellh/go-homedir"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
var cfgFile string
|
||||
|
||||
// rootCmd represents the base command when called without any subcommands
|
||||
var rootCmd = &cobra.Command{
|
||||
Use: "jwt",
|
||||
Short: "JWT(Json Web Token) 工具",
|
||||
Long: `JWT(Json Web Token) 工具
|
||||
用于生成、验证、查看 JWT`,
|
||||
Version: "v0.0.1",
|
||||
}
|
||||
|
||||
// Execute adds all child commands to the root command and sets flags appropriately.
|
||||
// This is called by main.main(). It only needs to happen once to the rootCmd.
|
||||
func Execute() {
|
||||
if err := rootCmd.Execute(); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
|
||||
func init() {
|
||||
cobra.OnInitialize(initConfig)
|
||||
|
||||
rootCmd.PersistentFlags().StringVar(&cfgFile, "config", "", "config file (default is $HOME/.jwt.yaml)")
|
||||
// rootCmd.Flags().BoolP("help", "h", false, "path to JWT token to verify or '-' to read from stdin")
|
||||
rootCmd.Flags().BoolP("version", "v", false, "show version of the jwt.")
|
||||
}
|
||||
|
||||
// initConfig reads in config file and ENV variables if set.
|
||||
func initConfig() {
|
||||
if cfgFile != "" {
|
||||
// Use config file from the flag.
|
||||
viper.SetConfigFile(cfgFile)
|
||||
} else {
|
||||
// Find home directory.
|
||||
home, err := homedir.Dir()
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
// Search config in home directory with name ".jwt" (without extension).
|
||||
viper.AddConfigPath(home)
|
||||
viper.SetConfigName(".jwt")
|
||||
}
|
||||
|
||||
viper.AutomaticEnv() // read in environment variables that match
|
||||
|
||||
// If a config file is found, read it in.
|
||||
if err := viper.ReadInConfig(); err == nil {
|
||||
fmt.Println("Using config file:", viper.ConfigFileUsed())
|
||||
}
|
||||
}
|
49
cmd/show.go
Normal file
49
cmd/show.go
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright © 2018 ehlxr <ehlxr.me@gmail.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/ehlxr/jwt/token"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// showCmd represents the show command
|
||||
var showCmd = &cobra.Command{
|
||||
Use: "show",
|
||||
Short: "查看 JWT Token",
|
||||
Long: `
|
||||
查看 JWT Token`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := token.ShowToken(cmd); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(showCmd)
|
||||
|
||||
showCmd.Flags().StringP("token", "t", "", "path or arg of JWT token to verify, '-' to read from clipboard")
|
||||
}
|
52
cmd/sign.go
Normal file
52
cmd/sign.go
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright © 2018 ehlxr <ehlxr.me@gmail.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/ehlxr/jwt/token"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// signCmd represents the sign command
|
||||
var signCmd = &cobra.Command{
|
||||
Use: "sign",
|
||||
Short: "JWT 签名",
|
||||
Long: `
|
||||
JWT 签名`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := token.SignToken(cmd); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(signCmd)
|
||||
|
||||
signCmd.Flags().StringP("data", "d", "", "path or json to claims object to sign, '-' to read from clipboard, or '+' to use only -claim args")
|
||||
signCmd.Flags().StringP("key", "k", "", "path of keyfile or key argument")
|
||||
signCmd.Flags().VarP(make(token.ArgList), "claims", "c", "add additional claims. may be used more than once")
|
||||
signCmd.Flags().VarP(make(token.ArgList), "header", "H", "add additional header params. may be used more than once")
|
||||
}
|
52
cmd/verify.go
Normal file
52
cmd/verify.go
Normal file
@ -0,0 +1,52 @@
|
||||
// Copyright © 2018 ehlxr <ehlxr.me@gmail.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
|
||||
"github.com/ehlxr/jwt/token"
|
||||
|
||||
"fmt"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// verifyCmd represents the verify command
|
||||
var verifyCmd = &cobra.Command{
|
||||
Use: "verify",
|
||||
Short: "JWT token 验证",
|
||||
Long: `
|
||||
JWT token 验证`,
|
||||
Run: func(cmd *cobra.Command, args []string) {
|
||||
if err := token.VerifyToken(cmd); err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
func init() {
|
||||
rootCmd.AddCommand(verifyCmd)
|
||||
|
||||
verifyCmd.Flags().StringP("token", "t", "", "path or arg of JWT token to verify, '-' to read from clipboard")
|
||||
verifyCmd.Flags().StringP("key", "k", "", "path of keyfile or key argument")
|
||||
}
|
6
demo.json
Normal file
6
demo.json
Normal file
@ -0,0 +1,6 @@
|
||||
{
|
||||
"foo": "bar",
|
||||
"exp": "2108-02-03",
|
||||
"info": "jjjkk",
|
||||
"other": "靠捡垃圾困了就睡打发士大夫斯柯达房间爱劳动法"
|
||||
}
|
1
demo.token
Normal file
1
demo.token
Normal file
@ -0,0 +1 @@
|
||||
eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOiIyMTA4LTAyLTAzIiwiZm9vIjoiYmFyIiwiaW5mbyI6ImpqamtrIiwib3RoZXIiOiLpnaDmjaHlnoPlnL7lm7DkuoblsLHnnaHmiZPlj5Hlo6vlpKflpKvmlq_mn6_ovr7miL_pl7TniLHlirPliqjms5UifQ.lwIz_fjoxHkgaBLUnBsRO0_zCmx4bEKNP_noW0dIGSSV5dPReb_E41Dg38G0ZB6tUFgH9k7aKsUUdMO3-ixRQ-nVT7qryLVti72G7Bpxy-_0FcwPWsvOl1ic8wCMtXLcL2FmcxFt4VC7nky1iAMCYn0iWyBxuPboNxBYNJF2TYB5rsfoLGgQ-okFVahZWDrdiepIlwFh-SkzrgLYzFhUgfCvCOFyTn65aNzJxY_3vxd4OSl6ks8C6J1qF7FZbFVFpcaHebZHjqg2rS3q0CdhN1IpGhEHC4dktpbeAzUYTPaohJWa-Rftthg4iM9DOFz8NBB_rNxyCYBfsbcywk8X2g
|
27
key/private-key.pem
Normal file
27
key/private-key.pem
Normal file
@ -0,0 +1,27 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIEpQIBAAKCAQEAtLcqUewX4sOPUUcocUi4EMMi25I52j9AHpphV4xZ5uUBzUuE
|
||||
sEuomPhvpElrVGAnla6856nrsSOTnw/pQ+wHkZLXXBbJOqdOH8wohch6v3lJoJDS
|
||||
FsCc+Y2OfolxZ8qz1Qq+AyvFGv4NIM0rWsfosrSsMDnQzLFtUoAfCMGU4uas2H1u
|
||||
Wfh+dDaABgxshAtmBuTyFJ/q36mGAznGzN7jVUSxv+pgI6AyEgxiIKOmFrz9qm6N
|
||||
s/H9fONQznnZouFZc0p3PME4xJcpdjET2tpACBZr6p7znFCm7t2BMrC37wznHUxC
|
||||
xP3XOugH9fs90EXV3XwPHZTAkvxvs8fpeDfGhwIDAQABAoIBAQCbsyhqNuEJhnZn
|
||||
j8h/eijkgEv7JAxmRpKnC1oNBSa8MdkQmR00i6sySPJfeMZZhxLz+v5VFuiz0TQy
|
||||
GpJe6/BFc1/LvvIXb+h2qv7K7UUczZIrHjt0UPWuaVE5IpAr3dB9IGk/8Ck9rV+A
|
||||
QGU3LQAHYHTuhBGrGr9XEn4qnCb8KlH/h12YEomIlp0+5TG6j4U6gzCJYM8MSmmP
|
||||
ms3JYP3jCvCD+UWcHXcWd/MAs4vfQAcCSvrrwrjHB0SZNAgUeIYxiXje1sKS5SU5
|
||||
tCKp7B7+PwBXkOMPPBxB93GsEmc6Tnw48hvl/xhOThOQ3zI608mzd83YQ7XU0cxO
|
||||
0LtAdyURAoGBAOFD3Ba1mL4MdYuSMpEH4Teu+rmuVBvF9tIA8uI73ZZDxOrklZRr
|
||||
XUtDcDwlsaSgk2ATz15+Rr+pYT3H3xl95P/xj2LG5SNY2OmiANALYHm71wDAa3xD
|
||||
th5p6QJ1wqQxzEBewwqXrm49YZr5eNU+rvTjsW4YcSB9ObYBbSUGvqf5AoGBAM1f
|
||||
Qu4pYrIfkPFhgDQaepDhZ41NGIaDmukZcorVPnliy4+anMoivvVjVNkUb7FyHm8h
|
||||
Fo2q6gSyeGDVGg/6QbMrzIrN5fqjCK4M4cBwd3sboctjI8fwJQB2+Wb6iOCQMU1W
|
||||
DbJ/edhOdLZ71lQMd+f5iQvhiZJPGLZnAxHyhoJ/AoGBANqvrU9illkR8V9A29RO
|
||||
SQds2L1ADykzQ01WXHTi11iUi+vZY5lFrbluS9woX8/Jj6k7MhqzDm3suplmmyC9
|
||||
Rn5ufNvQ6QwqqdIOUymlkdA8WhrBstddSMU33lxkBESwj3CCTmjPHiipcEMqI3Mp
|
||||
umHFVi/ijJiU2Vzm/5VtedPJAoGAQ5WI0hVefF209ipu5TadhRYYXMC1RHcEwJb2
|
||||
QcfhMlMXyB9KX57Flr1ki7eU9iEm8M1DvcU0E+2jfcJDPGTPwCW2vyr49t02Gwj0
|
||||
Nb8NIr86JFNwz/gwRRHiC0iBSN1KzDd4dHhM4akX8YGZS7l6sCVHO1iyTCqpaEVI
|
||||
FlzodQMCgYEAlMyxMLwaePE1NPgPqUeLcjfId42AZ64sVjoNG3awzj6pr3kV9mjp
|
||||
3GxFFDLdELZcsD5aJ5YSFbjMvUqSyyuFlZOAut06iUtPAN7fC57PdXGpcf2YkoK3
|
||||
PPK4mrwSlB4Onk8BQ3HfyGC5jzNsl+mnUHrRljWyzhdwQXtj65zQCD4=
|
||||
-----END RSA PRIVATE KEY-----
|
9
key/public-key.pem
Normal file
9
key/public-key.pem
Normal file
@ -0,0 +1,9 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAtLcqUewX4sOPUUcocUi4
|
||||
EMMi25I52j9AHpphV4xZ5uUBzUuEsEuomPhvpElrVGAnla6856nrsSOTnw/pQ+wH
|
||||
kZLXXBbJOqdOH8wohch6v3lJoJDSFsCc+Y2OfolxZ8qz1Qq+AyvFGv4NIM0rWsfo
|
||||
srSsMDnQzLFtUoAfCMGU4uas2H1uWfh+dDaABgxshAtmBuTyFJ/q36mGAznGzN7j
|
||||
VUSxv+pgI6AyEgxiIKOmFrz9qm6Ns/H9fONQznnZouFZc0p3PME4xJcpdjET2tpA
|
||||
CBZr6p7znFCm7t2BMrC37wznHUxCxP3XOugH9fs90EXV3XwPHZTAkvxvs8fpeDfG
|
||||
hwIDAQAB
|
||||
-----END PUBLIC KEY-----
|
27
main.go
Normal file
27
main.go
Normal file
@ -0,0 +1,27 @@
|
||||
// Copyright © 2018 ehlxr <ehlxr.me@gmail.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package main
|
||||
|
||||
import "github.com/ehlxr/jwt/cmd"
|
||||
|
||||
func main() {
|
||||
cmd.Execute()
|
||||
}
|
68
token/showtoken.go
Normal file
68
token/showtoken.go
Normal file
@ -0,0 +1,68 @@
|
||||
// Copyright © 2018 ehlxr <ehlxr.me@gmail.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package token
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
jwt "github.com/dgrijalva/jwt-go"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// showToken pretty-prints the token on the command line.
|
||||
func ShowToken(cmd *cobra.Command) error {
|
||||
flagToken := cmd.LocalFlags().Lookup("token").Value.String()
|
||||
flagDebug := promptDebug()
|
||||
flagCompact := promptCompact()
|
||||
|
||||
// get the token
|
||||
tokData, err := loadData(flagToken)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Couldn't read token: %v", err)
|
||||
}
|
||||
|
||||
// trim possible whitespace from token
|
||||
tokData = regexp.MustCompile(`\s*$`).ReplaceAll(tokData, []byte{})
|
||||
if flagDebug {
|
||||
fmt.Fprintf(os.Stderr, "Token len: %v bytes\n", len(tokData))
|
||||
}
|
||||
|
||||
token, err := jwt.Parse(string(tokData), nil)
|
||||
if token == nil {
|
||||
return fmt.Errorf("malformed token: %v", err)
|
||||
}
|
||||
|
||||
// Print the token details
|
||||
fmt.Println("Header:")
|
||||
if err := printJSON(token.Header, flagCompact); err != nil {
|
||||
return fmt.Errorf("Failed to output header: %v", err)
|
||||
}
|
||||
|
||||
fmt.Println("Claims:")
|
||||
if err := printJSON(token.Claims, flagCompact); err != nil {
|
||||
return fmt.Errorf("Failed to output claims: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
122
token/signtoken.go
Normal file
122
token/signtoken.go
Normal file
@ -0,0 +1,122 @@
|
||||
// Copyright © 2018 ehlxr <ehlxr.me@gmail.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package token
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
"github.com/atotto/clipboard"
|
||||
|
||||
jwt "github.com/dgrijalva/jwt-go"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Create, sign, and output a token. This is a great, simple example of
|
||||
// how to use this library to create and sign a token.
|
||||
func SignToken(cmd *cobra.Command) error {
|
||||
flagData := cmd.LocalFlags().Lookup("data").Value.String()
|
||||
flagClaims := cmd.LocalFlags().Lookup("claims").Value.(ArgList)
|
||||
flagHead := cmd.LocalFlags().Lookup("header").Value.(ArgList)
|
||||
flagKey := cmd.LocalFlags().Lookup("key").Value.String()
|
||||
flagDebug := promptDebug()
|
||||
|
||||
flagAlg, err := promptAlg()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Prompt flagAlg failed %v\n", err)
|
||||
}
|
||||
|
||||
// get the token data from command line arguments
|
||||
tokData, err := loadData(flagData)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Couldn't read data: %v", err)
|
||||
} else if flagDebug {
|
||||
fmt.Fprintf(os.Stderr, "Token len: %v bytes\n", len(tokData))
|
||||
fmt.Fprintf(os.Stderr, "Token data: %v \n", string(tokData))
|
||||
}
|
||||
|
||||
// parse the JSON of the claims
|
||||
var claims jwt.MapClaims
|
||||
if err := json.Unmarshal(tokData, &claims); err != nil {
|
||||
return fmt.Errorf("Couldn't parse claims JSON: %v", err)
|
||||
}
|
||||
|
||||
// add command line claims
|
||||
if len(flagClaims) > 0 {
|
||||
for k, v := range flagClaims {
|
||||
claims[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
// get the key
|
||||
var key interface{}
|
||||
key, err = loadData(flagKey)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Couldn't read key: %v", err)
|
||||
}
|
||||
|
||||
// get the signing alg
|
||||
alg := jwt.GetSigningMethod(flagAlg)
|
||||
if alg == nil {
|
||||
return fmt.Errorf("Couldn't find signing method alg: %v", flagAlg)
|
||||
}
|
||||
|
||||
// create a new token
|
||||
token := jwt.NewWithClaims(alg, claims)
|
||||
|
||||
// add command line headers
|
||||
if len(flagHead) > 0 {
|
||||
for k, v := range flagHead {
|
||||
token.Header[k] = v
|
||||
}
|
||||
}
|
||||
|
||||
if isEs(flagAlg) {
|
||||
if k, ok := key.([]byte); !ok {
|
||||
return fmt.Errorf("Couldn't convert key data to key")
|
||||
} else {
|
||||
key, err = jwt.ParseECPrivateKeyFromPEM(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
} else if isRs(flagAlg) {
|
||||
if k, ok := key.([]byte); !ok {
|
||||
return fmt.Errorf("Couldn't convert key data to key")
|
||||
} else {
|
||||
key, err = jwt.ParseRSAPrivateKeyFromPEM(k)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if out, err := token.SignedString(key); err == nil {
|
||||
fmt.Println(out)
|
||||
clipboard.WriteAll(out)
|
||||
} else {
|
||||
return fmt.Errorf("Error signing token: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
163
token/token.go
Normal file
163
token/token.go
Normal file
@ -0,0 +1,163 @@
|
||||
// Copyright © 2018 ehlxr <ehlxr.me@gmail.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package token
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/atotto/clipboard"
|
||||
|
||||
"github.com/manifoldco/promptui"
|
||||
)
|
||||
|
||||
// Helper func: Read input from specified file or string
|
||||
func loadData(p string) ([]byte, error) {
|
||||
if p == "" {
|
||||
return nil, fmt.Errorf("No path or arg specified")
|
||||
}
|
||||
|
||||
var rdr io.Reader
|
||||
if p == "-" {
|
||||
t, _ := clipboard.ReadAll()
|
||||
fmt.Printf("read data from clipboard: %s\n", t)
|
||||
rdr = strings.NewReader(t)
|
||||
} else if p == "+" {
|
||||
return []byte("{}"), nil
|
||||
} else {
|
||||
is, path := isPath(p)
|
||||
if is {
|
||||
if f, err := os.Open(path); err == nil {
|
||||
rdr = f
|
||||
defer f.Close()
|
||||
} else {
|
||||
return nil, err
|
||||
}
|
||||
} else {
|
||||
rdr = strings.NewReader(p)
|
||||
}
|
||||
}
|
||||
return ioutil.ReadAll(rdr)
|
||||
}
|
||||
|
||||
func isPath(path string) (bool, string) {
|
||||
p, err := filepath.Abs("")
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
absPath := filepath.Join(p, strings.Replace(path, p, "", 1))
|
||||
_, err = os.Stat(absPath)
|
||||
if err == nil {
|
||||
return true, absPath
|
||||
}
|
||||
return false, ""
|
||||
}
|
||||
|
||||
// Print a json object in accordance with the prophecy (or the command line options)
|
||||
func printJSON(j interface{}, flagCompact bool) error {
|
||||
var out []byte
|
||||
var err error
|
||||
|
||||
if flagCompact == false {
|
||||
out, err = json.MarshalIndent(j, "", " ")
|
||||
} else {
|
||||
out, err = json.Marshal(j)
|
||||
}
|
||||
|
||||
if err == nil {
|
||||
fmt.Println(string(out))
|
||||
}
|
||||
|
||||
return err
|
||||
}
|
||||
|
||||
func isEs(flagAlg string) bool {
|
||||
return strings.HasPrefix(flagAlg, "ES")
|
||||
}
|
||||
|
||||
func isRs(flagAlg string) bool {
|
||||
return strings.HasPrefix(flagAlg, "RS")
|
||||
}
|
||||
|
||||
func promptAlg() (string, error) {
|
||||
prompt := promptui.SelectWithAdd{
|
||||
Label: "select a signing algorithm identifier",
|
||||
Items: []string{"HS256", "RS256"},
|
||||
AddLabel: "Other",
|
||||
}
|
||||
_, flagAlg, err := prompt.Run()
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("Prompt flagAlg failed %v\n", err)
|
||||
}
|
||||
|
||||
return flagAlg, nil
|
||||
}
|
||||
|
||||
func promptDebug() bool {
|
||||
prompt := promptui.Prompt{
|
||||
Label: "print out all kinds of debug data",
|
||||
IsConfirm: true,
|
||||
}
|
||||
|
||||
if _, err := prompt.Run(); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func promptCompact() bool {
|
||||
prompt := promptui.Prompt{
|
||||
Label: "output compact JSON",
|
||||
IsConfirm: true,
|
||||
}
|
||||
|
||||
if _, err := prompt.Run(); err != nil {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
type ArgList map[string]string
|
||||
|
||||
func (l ArgList) String() string {
|
||||
data, _ := json.Marshal(l)
|
||||
return string(data)
|
||||
}
|
||||
|
||||
func (l ArgList) Set(arg string) error {
|
||||
parts := strings.SplitN(arg, "=", 2)
|
||||
if len(parts) != 2 {
|
||||
return fmt.Errorf("Invalid argument '%v'. Must use format 'key=value'. %v", arg, parts)
|
||||
}
|
||||
l[parts[0]] = parts[1]
|
||||
return nil
|
||||
}
|
||||
|
||||
func (l ArgList) Type() string {
|
||||
return "argList"
|
||||
}
|
93
token/verifytoken.go
Normal file
93
token/verifytoken.go
Normal file
@ -0,0 +1,93 @@
|
||||
// Copyright © 2018 ehlxr <ehlxr.me@gmail.com>
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
// THE SOFTWARE.
|
||||
|
||||
package token
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"regexp"
|
||||
|
||||
jwt "github.com/dgrijalva/jwt-go"
|
||||
"github.com/spf13/cobra"
|
||||
)
|
||||
|
||||
// Verify a token and output the claims. This is a great example
|
||||
// of how to verify and view a token.
|
||||
func VerifyToken(cmd *cobra.Command) error {
|
||||
flagToken := cmd.LocalFlags().Lookup("token").Value.String()
|
||||
flagKey := cmd.LocalFlags().Lookup("key").Value.String()
|
||||
flagCompact := promptCompact()
|
||||
flagDebug := promptDebug()
|
||||
|
||||
flagAlg, err := promptAlg()
|
||||
if err != nil {
|
||||
return fmt.Errorf("Prompt flagAlg failed %v\n", err)
|
||||
}
|
||||
|
||||
// get the token
|
||||
tokData, err := loadData(flagToken)
|
||||
if err != nil {
|
||||
return fmt.Errorf("Couldn't read token: %v", err)
|
||||
}
|
||||
|
||||
// trim possible whitespace from token
|
||||
tokData = regexp.MustCompile(`\s*$`).ReplaceAll(tokData, []byte{})
|
||||
if flagDebug {
|
||||
fmt.Fprintf(os.Stderr, "Token len: %v bytes\n", len(tokData))
|
||||
}
|
||||
|
||||
// Parse the token. Load the key from command line option
|
||||
token, err := jwt.Parse(string(tokData), func(t *jwt.Token) (interface{}, error) {
|
||||
data, err := loadData(flagKey)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if isEs(flagAlg) {
|
||||
return jwt.ParseECPublicKeyFromPEM(data)
|
||||
} else if isRs(flagAlg) {
|
||||
return jwt.ParseRSAPublicKeyFromPEM(data)
|
||||
}
|
||||
return data, nil
|
||||
})
|
||||
|
||||
// Print some debug data
|
||||
if flagDebug && token != nil {
|
||||
fmt.Fprintf(os.Stderr, "Header:\n%v\n", token.Header)
|
||||
fmt.Fprintf(os.Stderr, "Claims:\n%v\n", token.Claims)
|
||||
}
|
||||
|
||||
// Print an error if we can't parse for some reason
|
||||
if err != nil {
|
||||
return fmt.Errorf("Couldn't parse token: %v", err)
|
||||
}
|
||||
|
||||
// Is token invalid?
|
||||
if !token.Valid {
|
||||
return fmt.Errorf("Token is invalid")
|
||||
}
|
||||
|
||||
// Print the token details
|
||||
if err := printJSON(token.Claims, flagCompact); err != nil {
|
||||
return fmt.Errorf("Failed to output claims: %v", err)
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
Loading…
Reference in New Issue
Block a user