客户端代码编写
This commit is contained in:
@@ -1,16 +1,17 @@
|
||||
package org.nl.sso.base;
|
||||
|
||||
import cn.dev33.satoken.SaManager;
|
||||
import cn.dev33.satoken.config.SaSsoConfig;
|
||||
import cn.dev33.satoken.sso.SaSsoManager;
|
||||
import cn.dev33.satoken.sso.SaSsoProcessor;
|
||||
import cn.dev33.satoken.sso.SaSsoUtil;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.http.HttpRequest;
|
||||
import cn.hutool.http.HttpResponse;
|
||||
import cn.hutool.json.JSON;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import cn.hutool.jwt.JWT;
|
||||
import org.nl.sso.base.dto.UserEntry;
|
||||
import org.nl.sso.base.util.UserUtil;
|
||||
import org.springframework.boot.context.properties.ConfigurationProperties;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.web.servlet.HandlerInterceptor;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
@@ -21,31 +22,38 @@ import java.util.List;
|
||||
* @author ZZQ
|
||||
* @Date 2022/11/26 10:12 上午
|
||||
*/
|
||||
@Component
|
||||
@ConfigurationProperties(prefix = "sa-token.sso")
|
||||
public class LoginInterceptor implements HandlerInterceptor {
|
||||
private String pathPatterns;
|
||||
|
||||
private List whileUrl= Arrays.asList("auth/login","/error","/logout","auth/sso/logoutCall","/auth/logout");
|
||||
@Override
|
||||
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
|
||||
if (whileUrl.contains(request.getRequestURI())){
|
||||
return true;
|
||||
}
|
||||
String loginId = StpUtil.getLoginId(null);
|
||||
System.out.println("-- 登入请求---"+loginId);
|
||||
if (loginId ==null){
|
||||
return false;
|
||||
}else {
|
||||
UserEntry user = UserUtil.userCache.get(loginId);
|
||||
if (user ==null){
|
||||
//查询数据库
|
||||
HttpResponse execute = HttpRequest.get(SaSsoManager.getConfig().userinfoUrl + "?loginId=" + loginId).execute();
|
||||
if (200==execute.getStatus()){
|
||||
String body = execute.body();
|
||||
UserEntry info = new UserEntry();
|
||||
info.setTotalInfo(body);
|
||||
info.setUserId(Long.valueOf(loginId));
|
||||
UserUtil.setUserEntry(info);
|
||||
}
|
||||
}
|
||||
//如果需要添加token登出过期,修改过期添加redis判断:String token = SaSsoUtil.saSsoTemplate.stpLogic.isLogin
|
||||
String token = StpUtil.stpLogic.getTokenValue();
|
||||
if (!StringUtils.isEmpty(token)){
|
||||
JWT of = JWT.of(token);
|
||||
UserEntry user = of.getPayloads().get("loginInfo", UserEntry.class);
|
||||
UserUtil.setUserEntry(user);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception {
|
||||
UserUtil.remove();
|
||||
}
|
||||
|
||||
public String getPathPatterns() {
|
||||
return pathPatterns;
|
||||
}
|
||||
|
||||
public void setPathPatterns(String pathPatterns) {
|
||||
this.pathPatterns = pathPatterns;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,37 +1,54 @@
|
||||
package org.nl.sso.base.dto;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import lombok.Data;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
* @author ZZQ
|
||||
* @Date 2022/11/25 5:44 下午
|
||||
* String info ="{\"id\":1,\"username\":\"admin\",\"user\":{\"username\":\"admin\",\"personName\":\"管理员\",\"email\":\"201507802@qq.com\",\"phone\":\"18888888888\",\"gender\":\"男\",\"avatarName\":\"avatar-20200806032259161.png\",\"avatarPath\":\"/Users/jie/Documents/work/me/admin/eladmin/~/avatar/avatar-20200806032259161.png\",\"extuserId\":\"\",\"password\":\"f52020dca765fd3943ed40a615dc2c5c\",\"create_name\":\"\",\"update_optname\":\"admin\",\"create_time\":1669846199,\"update_time\":1669966881},\"permissions\":[\"admin\",\"user:list\",\"roles:list\",\"menu:list\",\"timing:list\",\"dept:list\",\"dict:list\",\"roles:add\",\"roles:edit\",\"roles:del\",\"monitor:list\",\"genCode:list\",\"999\",\"storage:list\"]}";
|
||||
*/
|
||||
@Data
|
||||
public class UserEntry implements Serializable {
|
||||
private Long userId;
|
||||
private String userName;
|
||||
private String totalInfo;
|
||||
|
||||
public Long getUserId() {
|
||||
return userId;
|
||||
}
|
||||
private Integer id;
|
||||
private String username;
|
||||
private User user;
|
||||
private List<String> permissions;
|
||||
private List<String> roles;
|
||||
|
||||
public void setUserId(Long userId) {
|
||||
this.userId = userId;
|
||||
}
|
||||
@Data
|
||||
public class User{
|
||||
private String username;
|
||||
/** 昵称 */
|
||||
private String personName;
|
||||
/** 性别 */
|
||||
private String gender;
|
||||
/** 手机号码 */
|
||||
private String phone;
|
||||
/** 邮箱 */
|
||||
private String email;
|
||||
/** 头像地址 */
|
||||
private String avatarName;
|
||||
/** 头像真实路径 */
|
||||
private String avatarPath;
|
||||
/** 密码 */
|
||||
private String password;
|
||||
/** 创建者 */
|
||||
private String create_by;
|
||||
/** 更新者 */
|
||||
private String update_by;
|
||||
/** 修改密码的时间 */
|
||||
private Date pwd_reset_time;
|
||||
/** 创建日期 */
|
||||
private Date create_time;
|
||||
/** 更新时间 */
|
||||
private Date update_time;
|
||||
|
||||
public String getUserName() {
|
||||
return userName;
|
||||
}
|
||||
|
||||
public void setUserName(String userName) {
|
||||
this.userName = userName;
|
||||
}
|
||||
|
||||
public String getTotalInfo() {
|
||||
return totalInfo;
|
||||
}
|
||||
|
||||
public void setTotalInfo(String totalInfo) {
|
||||
this.totalInfo = totalInfo;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -18,16 +18,13 @@ import org.springframework.web.servlet.config.annotation.WebMvcConfigurer;
|
||||
* @Date 2022/11/24 3:55 下午
|
||||
*/
|
||||
@Configuration
|
||||
@ConfigurationProperties(prefix = "sa-token.sso")
|
||||
public class BaseConfig implements WebMvcConfigurer {
|
||||
|
||||
private String pathPatterns ="/**";
|
||||
private String projectName ="上海诺力欢迎你";
|
||||
|
||||
@Override
|
||||
public void addInterceptors(InterceptorRegistry registry) {
|
||||
// 注册 Sa-Token 拦截器,打开注解式鉴权功能
|
||||
registry.addInterceptor(new SaInterceptor()).addPathPatterns(pathPatterns);
|
||||
registry.addInterceptor(new SaInterceptor()).addPathPatterns("/**");
|
||||
registry.addInterceptor(new LoginInterceptor()).addPathPatterns("/**");
|
||||
}
|
||||
|
||||
@@ -36,23 +33,12 @@ public class BaseConfig implements WebMvcConfigurer {
|
||||
// 配置Http请求处理器
|
||||
sso.setSendHttp(url -> {
|
||||
HttpResponse execute = HttpRequest.get(url).execute();
|
||||
return execute.body();
|
||||
if (execute.getStatus() == 200){
|
||||
return execute.body();
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
public String getPathPatterns() {
|
||||
return pathPatterns;
|
||||
}
|
||||
|
||||
public void setPathPatterns(String pathPatterns) {
|
||||
this.pathPatterns = pathPatterns;
|
||||
}
|
||||
|
||||
public String getProjectName() {
|
||||
return projectName;
|
||||
}
|
||||
|
||||
public void setProjectName(String projectName) {
|
||||
this.projectName = projectName;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,12 @@
|
||||
package org.nl.sso.base.saconfig;
|
||||
|
||||
import cn.dev33.satoken.stp.StpInterface;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
import cn.hutool.json.JSONArray;
|
||||
import cn.hutool.json.JSONObject;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/*
|
||||
@@ -14,11 +18,21 @@ import java.util.List;
|
||||
public final class PermissionHandler implements StpInterface {
|
||||
@Override
|
||||
public List<String> getPermissionList(Object loginId, String loginType) {
|
||||
return null;
|
||||
JSONObject json = (JSONObject) StpUtil.getExtra("loginInfo");
|
||||
JSONArray permissions = json.getJSONArray("permissions");
|
||||
if (permissions.size() > 0) {
|
||||
return permissions.toList(String.class);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getRoleList(Object loginId, String loginType) {
|
||||
return null;
|
||||
JSONObject json = (JSONObject) StpUtil.getExtra("loginInfo");
|
||||
JSONArray roles = json.getJSONArray("roles");
|
||||
if (roles.size() > 0) {
|
||||
return roles.toList(String.class);
|
||||
}
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
package org.nl.sso.controller;
|
||||
|
||||
import cn.dev33.satoken.sso.SaSsoManager;
|
||||
import cn.dev33.satoken.sso.SaSsoProcessor;
|
||||
import cn.dev33.satoken.stp.StpUtil;
|
||||
|
||||
import cn.dev33.satoken.sso.SaSsoUtil;
|
||||
|
||||
import com.alibaba.fastjson.JSONObject;
|
||||
import org.nl.sso.base.util.UserUtil;
|
||||
import org.springframework.http.*;
|
||||
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
|
||||
/*
|
||||
@@ -20,33 +19,25 @@ import org.springframework.web.servlet.ModelAndView;
|
||||
@RequestMapping("auth")
|
||||
public class LoginController {
|
||||
|
||||
//首页登入测试页面
|
||||
@RequestMapping("/login")
|
||||
public ModelAndView login(ModelAndView mv) {
|
||||
String authUrl = SaSsoManager.getConfig().splicingAuthUrl();
|
||||
mv.setViewName("login");
|
||||
mv.addObject("title","上海诺力欢迎你");
|
||||
mv.addObject("authUrl",authUrl+"?mode=simple&redirect=http://localhost:8080/home");
|
||||
mv.addObject("isLogin",StpUtil.isLogin());
|
||||
return mv;
|
||||
}
|
||||
//获取用户信息:包括权限角色菜单等
|
||||
@RequestMapping("/info")
|
||||
public String userInfo() {
|
||||
String totalInfo = UserUtil.getUserInfo().getTotalInfo();
|
||||
return totalInfo;
|
||||
public ResponseEntity<Object> userInfo() {
|
||||
Object body = SaSsoUtil.getUserinfo(UserUtil.getUserInfo().getId());
|
||||
if (body !=null){
|
||||
String info = (String) body;
|
||||
return ResponseEntity.ok(JSONObject.parseObject(info));
|
||||
}
|
||||
return ResponseEntity.noContent().build();
|
||||
}
|
||||
//首页登入测试页面
|
||||
@RequestMapping("/logout")
|
||||
public ResponseEntity logout() {
|
||||
SaSsoProcessor.instance.ssoLogout();
|
||||
|
||||
return new ResponseEntity<>(HttpStatus.OK);
|
||||
}
|
||||
|
||||
@RequestMapping("/sso/logoutCall")
|
||||
public void logoutCall() {
|
||||
System.out.println("-----"+"服务端回调注销");
|
||||
SaSsoProcessor.instance.ssoLogoutCall();
|
||||
}
|
||||
// @RequestMapping("/sso/logoutCall")
|
||||
// public void logoutCall() {
|
||||
// System.out.println("-----"+"服务端回调注销用,");
|
||||
// }
|
||||
|
||||
}
|
||||
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,2 +0,0 @@
|
||||
/*! layer mobile-v2.0.0 Web弹层组件 MIT License http://layer.layui.com/mobile By 贤心 */
|
||||
;!function(e){"use strict";var t=document,n="querySelectorAll",i="getElementsByClassName",a=function(e){return t[n](e)},s={type:0,shade:!0,shadeClose:!0,fixed:!0,anim:"scale"},l={extend:function(e){var t=JSON.parse(JSON.stringify(s));for(var n in e)t[n]=e[n];return t},timer:{},end:{}};l.touch=function(e,t){e.addEventListener("click",function(e){t.call(this,e)},!1)};var r=0,o=["layui-m-layer"],c=function(e){var t=this;t.config=l.extend(e),t.view()};c.prototype.view=function(){var e=this,n=e.config,s=t.createElement("div");e.id=s.id=o[0]+r,s.setAttribute("class",o[0]+" "+o[0]+(n.type||0)),s.setAttribute("index",r);var l=function(){var e="object"==typeof n.title;return n.title?'<h3 style="'+(e?n.title[1]:"")+'">'+(e?n.title[0]:n.title)+"</h3>":""}(),c=function(){"string"==typeof n.btn&&(n.btn=[n.btn]);var e,t=(n.btn||[]).length;return 0!==t&&n.btn?(e='<span yes type="1">'+n.btn[0]+"</span>",2===t&&(e='<span no type="0">'+n.btn[1]+"</span>"+e),'<div class="layui-m-layerbtn">'+e+"</div>"):""}();if(n.fixed||(n.top=n.hasOwnProperty("top")?n.top:100,n.style=n.style||"",n.style+=" top:"+(t.body.scrollTop+n.top)+"px"),2===n.type&&(n.content='<i></i><i class="layui-m-layerload"></i><i></i><p>'+(n.content||"")+"</p>"),n.skin&&(n.anim="up"),"msg"===n.skin&&(n.shade=!1),s.innerHTML=(n.shade?"<div "+("string"==typeof n.shade?'style="'+n.shade+'"':"")+' class="layui-m-layershade"></div>':"")+'<div class="layui-m-layermain" '+(n.fixed?"":'style="position:static;"')+'><div class="layui-m-layersection"><div class="layui-m-layerchild '+(n.skin?"layui-m-layer-"+n.skin+" ":"")+(n.className?n.className:"")+" "+(n.anim?"layui-m-anim-"+n.anim:"")+'" '+(n.style?'style="'+n.style+'"':"")+">"+l+'<div class="layui-m-layercont">'+n.content+"</div>"+c+"</div></div></div>",!n.type||2===n.type){var d=t[i](o[0]+n.type),y=d.length;y>=1&&layer.close(d[0].getAttribute("index"))}document.body.appendChild(s);var u=e.elem=a("#"+e.id)[0];n.success&&n.success(u),e.index=r++,e.action(n,u)},c.prototype.action=function(e,t){var n=this;e.time&&(l.timer[n.index]=setTimeout(function(){layer.close(n.index)},1e3*e.time));var a=function(){var t=this.getAttribute("type");0==t?(e.no&&e.no(),layer.close(n.index)):e.yes?e.yes(n.index):layer.close(n.index)};if(e.btn)for(var s=t[i]("layui-m-layerbtn")[0].children,r=s.length,o=0;o<r;o++)l.touch(s[o],a);if(e.shade&&e.shadeClose){var c=t[i]("layui-m-layershade")[0];l.touch(c,function(){layer.close(n.index,e.end)})}e.end&&(l.end[n.index]=e.end)},e.layer={v:"2.0",index:r,open:function(e){var t=new c(e||{});return t.index},close:function(e){var n=a("#"+o[0]+e)[0];n&&(n.innerHTML="",t.body.removeChild(n),clearTimeout(l.timer[e]),delete l.timer[e],"function"==typeof l.end[e]&&l.end[e](),delete l.end[e])},closeAll:function(){for(var e=t[i](o[0]),n=0,a=e.length;n<a;n++)layer.close(0|e[0].getAttribute("index"))}},"function"==typeof define?define(function(){return layer}):function(){var e=document.scripts,n=e[e.length-1],i=n.src,a=i.substring(0,i.lastIndexOf("/")+1);n.getAttribute("merge")||document.head.appendChild(function(){var e=t.createElement("link");return e.href=a+"need/layer.css?2.0",e.type="text/css",e.rel="styleSheet",e.id="layermcss",e}())}()}(window);
|
||||
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 5.8 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 11 KiB |
File diff suppressed because one or more lines are too long
Binary file not shown.
|
Before Width: | Height: | Size: 5.7 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 701 B |
Binary file not shown.
|
Before Width: | Height: | Size: 1.7 KiB |
@@ -1,59 +0,0 @@
|
||||
*{margin: 0; padding: 0;}
|
||||
body{font-family: Helvetica Neue,Helvetica,PingFang SC,Tahoma,Arial,sans-serif;}
|
||||
::-webkit-input-placeholder{color: #ccc;}
|
||||
|
||||
/* 视图盒子 */
|
||||
.view-box{position: relative; width: 100vw; height: 100vh; overflow: hidden;}
|
||||
/* 背景 EAEFF3 */
|
||||
.bg-1{height: 50%; background: linear-gradient(to bottom right, #0466c5, #3496F5);}
|
||||
.bg-2{height: 50%; background-color: #EAEFF3;}
|
||||
|
||||
/* 渐变背景 */
|
||||
/*.bg-1{
|
||||
background-size: 500%;
|
||||
background-image: linear-gradient(125deg,#0466c5,#3496F5,#0466c5,#3496F5,#0466c5,#2496F5);
|
||||
animation: bganimation 30s infinite;
|
||||
}
|
||||
@keyframes bganimation{
|
||||
0%{background-position: 0% 50%;}
|
||||
50%{background-position: 100% 50%;}
|
||||
100%{background-position: 0% 50%;}
|
||||
} */
|
||||
/* 背景 */
|
||||
.bg-1{background: #101C34;}
|
||||
.bg-2{background: #101C34;}
|
||||
/* .bg-1{height: 100%; background-image: url(./login-bg.png); background-size: 100% 100%;} */
|
||||
|
||||
|
||||
/* 内容盒子 */
|
||||
.content-box{position: absolute; width: 100vw; height: 100vh; top: 0px;}
|
||||
|
||||
/* 登录盒子 */
|
||||
/* .login-box{width: 400px; height: 400px; position: absolute; left: calc(50% - 200px); top: calc(50% - 200px); max-width: 90%; } */
|
||||
.login-box{width: 400px; margin: auto; max-width: 90%; height: 100%;}
|
||||
.login-box{display: flex; align-items: center; text-align: center;}
|
||||
|
||||
/* 表单 */
|
||||
.from-box{flex: 1; padding: 20px 50px; background-color: #FFF;}
|
||||
.from-box{border-radius: 1px; box-shadow: 1px 1px 20px #666;}
|
||||
.from-title{margin-top: 20px; margin-bottom: 30px; text-align: center;}
|
||||
|
||||
/* 输入框 */
|
||||
.from-item{border: 0px #000 solid; margin-bottom: 15px;}
|
||||
.s-input{width: 100%; line-height: 32px; height: 32px; text-indent: 1em; outline: 0; border: 1px #ccc solid; border-radius: 3px; transition: all 0.2s;}
|
||||
.s-input{font-size: 12px;}
|
||||
.s-input:focus{border-color: #409eff}
|
||||
|
||||
/* 登录按钮 */
|
||||
.s-btn{ text-indent: 0; cursor: pointer; background-color: #409EFF; border-color: #409EFF; color: #FFF;}
|
||||
.s-btn:hover{background-color: #50aEFF;}
|
||||
|
||||
/* 重置按钮 */
|
||||
.reset-box{text-align: left; font-size: 12px;}
|
||||
.reset-box a{text-decoration: none;}
|
||||
.reset-box a:hover{text-decoration: underline;}
|
||||
|
||||
/* loading框样式 */
|
||||
.ajax-layer-load.layui-layer-dialog{min-width: 0px !important; background-color: rgba(0,0,0,0.85);}
|
||||
.ajax-layer-load.layui-layer-dialog .layui-layer-content{padding: 10px 20px 10px 40px; color: #FFF;}
|
||||
.ajax-layer-load.layui-layer-dialog .layui-layer-content .layui-layer-ico{width: 20px; height: 20px; background-size: 20px 20px; top: 12px; }
|
||||
@@ -1,65 +0,0 @@
|
||||
// sa
|
||||
var sa = {};
|
||||
|
||||
// 打开loading
|
||||
sa.loading = function(msg) {
|
||||
layer.closeAll(); // 开始前先把所有弹窗关了
|
||||
return layer.msg(msg, {icon: 16, shade: 0.3, time: 1000 * 20, skin: 'ajax-layer-load' });
|
||||
};
|
||||
|
||||
// 隐藏loading
|
||||
sa.hideLoading = function() {
|
||||
layer.closeAll();
|
||||
};
|
||||
|
||||
|
||||
// ----------------------------------- 登录事件 -----------------------------------
|
||||
|
||||
$('.login-btn').click(function(){
|
||||
sa.loading("正在登录...");
|
||||
// 开始登录
|
||||
setTimeout(function() {
|
||||
$.ajax({
|
||||
url: "sso/doLogin",
|
||||
type: "post",
|
||||
data: {
|
||||
name: $('[name=name]').val(),
|
||||
pwd: $('[name=pwd]').val()
|
||||
},
|
||||
dataType: 'json',
|
||||
success: function(res){
|
||||
console.log('返回数据:', res);
|
||||
sa.hideLoading();
|
||||
if(res.code == 200) {
|
||||
layer.msg('登录成功', {anim: 0, icon: 6 });
|
||||
setTimeout(function() {
|
||||
location.reload();
|
||||
}, 800)
|
||||
} else {
|
||||
layer.msg(res.msg, {anim: 6, icon: 2 });
|
||||
}
|
||||
},
|
||||
error: function(xhr, type, errorThrown){
|
||||
sa.hideLoading();
|
||||
if(xhr.status == 0){
|
||||
return layer.alert('无法连接到服务器,请检查网络');
|
||||
}
|
||||
return layer.alert("异常:" + JSON.stringify(xhr));
|
||||
}
|
||||
});
|
||||
}, 400);
|
||||
});
|
||||
|
||||
// 绑定回车事件
|
||||
$('[name=name],[name=pwd]').bind('keypress', function(event){
|
||||
if(event.keyCode == "13") {
|
||||
$('.login-btn').click();
|
||||
}
|
||||
});
|
||||
|
||||
// 输入框获取焦点
|
||||
$("[name=name]").focus();
|
||||
|
||||
// 打印信息
|
||||
var str = "This page is provided by Sa-Token, Please refer to: " + "https://sa-token.cc/";
|
||||
console.log(str);
|
||||
@@ -1,17 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title th:text="${title}"></title>
|
||||
<base th:href="@{/}" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no">
|
||||
<link rel="stylesheet" href="./sa-res/login.css">
|
||||
</head>
|
||||
<body>
|
||||
<a th:text="${title}"></a>
|
||||
<a th:href="${authUrl}">登入</a>
|
||||
<a th:text="${isLogin}">当前登入状态:</a>
|
||||
|
||||
</body>
|
||||
</script>
|
||||
</html>
|
||||
Reference in New Issue
Block a user