添加spring security
This commit is contained in:
@@ -28,10 +28,11 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-freemarker</artifactId>
|
||||
</dependency>
|
||||
<!-- <dependency>
|
||||
<!-- spring security -->
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-security</artifactId>
|
||||
</dependency> -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-web</artifactId>
|
||||
@@ -46,16 +47,6 @@
|
||||
<artifactId>h2</artifactId>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
<!-- <dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency> -->
|
||||
<!-- <dependency>
|
||||
<groupId>org.springframework.security</groupId>
|
||||
<artifactId>spring-security-test</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency> -->
|
||||
<!-- https://mvnrepository.com/artifact/org.json/json -->
|
||||
<dependency>
|
||||
<groupId>org.json</groupId>
|
||||
@@ -109,9 +100,6 @@
|
||||
<plugin>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-maven-plugin</artifactId>
|
||||
<configuration>
|
||||
<failOnMissingWebXml>false</failOnMissingWebXml>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
@@ -0,0 +1,98 @@
|
||||
package com.yaoyuan.jiscuss.config;
|
||||
|
||||
import com.yaoyuan.jiscuss.handler.CustomAccessDeniedHandler;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Configurable;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
|
||||
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
|
||||
import org.springframework.security.config.annotation.web.builders.WebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
|
||||
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
|
||||
|
||||
/**
|
||||
prePostEnabled :决定Spring Security的前注解是否可用 [@PreAuthorize,@PostAuthorize,..]
|
||||
secureEnabled : 决定是否Spring Security的保障注解 [@Secured] 是否可用
|
||||
jsr250Enabled :决定 JSR-250 annotations 注解[@RolesAllowed..] 是否可用.
|
||||
*/
|
||||
@Configurable
|
||||
@EnableWebSecurity
|
||||
//开启 Spring Security 方法级安全注解 @EnableGlobalMethodSecurity
|
||||
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true,jsr250Enabled = true)
|
||||
public class WebSecurityConfig extends WebSecurityConfigurerAdapter{
|
||||
|
||||
@Autowired
|
||||
private CustomAccessDeniedHandler customAccessDeniedHandler;
|
||||
@Qualifier("userDetailServiceImpl")
|
||||
@Autowired
|
||||
private UserDetailsService userDetailsService;
|
||||
|
||||
/**
|
||||
* 静态资源设置
|
||||
*/
|
||||
@Override
|
||||
public void configure(WebSecurity webSecurity) {
|
||||
//不拦截静态资源,所有用户均可访问的资源
|
||||
webSecurity.ignoring().antMatchers(
|
||||
"/",
|
||||
"/css/**",
|
||||
"/js/**",
|
||||
"/images/**",
|
||||
"/static/**",
|
||||
"/index/**"
|
||||
);
|
||||
}
|
||||
/**
|
||||
* http请求设置
|
||||
*/
|
||||
@Override
|
||||
public void configure(HttpSecurity http) throws Exception {
|
||||
//http.csrf().disable(); //注释就是使用 csrf 功能
|
||||
http.headers().frameOptions().disable();//解决 in a frame because it set 'X-Frame-Options' to 'DENY' 问题
|
||||
//http.anonymous().disable();
|
||||
http.authorizeRequests()
|
||||
.antMatchers("/login/**","/initUserData")//不拦截登录相关方法
|
||||
.permitAll()
|
||||
//.antMatchers("/user").hasRole("ADMIN") // user接口只有ADMIN角色的可以访问
|
||||
// .anyRequest()
|
||||
// .authenticated()// 任何尚未匹配的URL只需要验证用户即可访问
|
||||
.anyRequest()
|
||||
.access("@rbacPermission.hasPermission(request, authentication)")//根据账号权限访问
|
||||
.and()
|
||||
.formLogin()
|
||||
// .loginPage("/")
|
||||
.loginPage("/login") //登录请求页
|
||||
.loginProcessingUrl("/login") //登录POST请求路径
|
||||
.usernameParameter("username") //登录用户名参数
|
||||
.passwordParameter("password") //登录密码参数
|
||||
.defaultSuccessUrl("/") //默认登录成功页面
|
||||
.and()
|
||||
.exceptionHandling()
|
||||
.accessDeniedHandler(customAccessDeniedHandler) //无权限处理器
|
||||
.and()
|
||||
.logout()
|
||||
.logoutSuccessUrl("/login?logout"); //退出登录成功URL
|
||||
|
||||
}
|
||||
/**
|
||||
* 自定义获取用户信息接口
|
||||
*/
|
||||
@Override
|
||||
public void configure(AuthenticationManagerBuilder auth) throws Exception {
|
||||
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder());
|
||||
}
|
||||
|
||||
/**
|
||||
* 密码加密算法
|
||||
* @return
|
||||
*/
|
||||
@Bean
|
||||
public BCryptPasswordEncoder passwordEncoder() {
|
||||
return new BCryptPasswordEncoder();
|
||||
|
||||
}
|
||||
}
|
||||
@@ -11,17 +11,20 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.domain.Page;
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.security.core.context.SecurityContext;
|
||||
import org.springframework.security.core.context.SecurityContextHolder;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.stereotype.Controller;
|
||||
import org.springframework.web.bind.annotation.PostMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.ResponseBody;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
import org.springframework.web.servlet.ModelAndView;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Enumeration;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -52,6 +55,28 @@ public class UserSystemController {
|
||||
List<Users> useral2 = usersService.getAllList();
|
||||
logger.info(">>> 第二遍的全部用户:"+useral2);
|
||||
|
||||
String username ="";
|
||||
//获得session对象
|
||||
HttpSession session = request.getSession();
|
||||
//取出session域中所有属性名
|
||||
Enumeration attributeNames = session.getAttributeNames();
|
||||
while (attributeNames.hasMoreElements()) {
|
||||
System.out.println(attributeNames.nextElement());
|
||||
}
|
||||
//SPRING_SECURITY_CONTEXT
|
||||
Object spring_security_context = session.getAttribute("SPRING_SECURITY_CONTEXT");
|
||||
System.out.println(spring_security_context);
|
||||
SecurityContext securityContext = (SecurityContext) spring_security_context;
|
||||
if(securityContext!=null){
|
||||
//获得认证信息
|
||||
Authentication authentication = securityContext.getAuthentication();
|
||||
//获得用户详情
|
||||
Object principal = authentication.getPrincipal();
|
||||
User user = (User) principal;
|
||||
username = user.getUsername();
|
||||
System.out.println(username);
|
||||
}
|
||||
|
||||
//分页获取主题帖子
|
||||
// List<Discussions> allDiscussions = discussionsService.getAllList();
|
||||
|
||||
@@ -64,18 +89,16 @@ public class UserSystemController {
|
||||
//获取主题帖子的分页数据
|
||||
List<String> pageNumList = getPageNumList(allDiscussionsPage.getTotalPages());
|
||||
|
||||
|
||||
//获取所有标签(以后尝试去缓存中取)
|
||||
List<Tags> allTags = tagsService.getAllList();
|
||||
logger.info("全部标签==>:{}",allTags);
|
||||
|
||||
HttpSession session=request.getSession();
|
||||
System.out.println(userall.toString());
|
||||
map.put("data", "Jiscuss 用户");
|
||||
map.put("allDiscussions", allDiscussions);
|
||||
map.put("pageDiscussions", pageNumList);
|
||||
map.put("allTags", allTags);
|
||||
map.put("username", session.getAttribute("username"));
|
||||
map.put("username", username);
|
||||
return "index";
|
||||
}
|
||||
|
||||
@@ -99,25 +122,41 @@ public class UserSystemController {
|
||||
|
||||
|
||||
//登录
|
||||
@PostMapping(value = "/login")
|
||||
@ResponseBody
|
||||
public String login(@RequestParam("username") String username, @RequestParam("password") String password,
|
||||
HttpSession session) {
|
||||
JSONObject resultobj = new JSONObject();
|
||||
Users user = usersService.checkByUsernameAndPassword(username, password);
|
||||
if (user!=null) {
|
||||
//用户名和密码完成校验
|
||||
session.setAttribute("username", username); //缓存session
|
||||
session.setAttribute("userid", user.getId()); //缓存session
|
||||
resultobj.put("username", username);
|
||||
resultobj.put("msg", "登录成功");
|
||||
resultobj.put("flag", true);
|
||||
} else {
|
||||
//用户名和密码未完成校验
|
||||
resultobj.put("msg", "用户名或密码错误");
|
||||
resultobj.put("flag", false);
|
||||
// @PostMapping(value = "/login")
|
||||
// @ResponseBody
|
||||
// public String login(@RequestParam("username") String username, @RequestParam("password") String password,
|
||||
// HttpSession session) {
|
||||
// JSONObject resultobj = new JSONObject();
|
||||
// Users user = usersService.checkByUsernameAndPassword(username, password);
|
||||
// if (user!=null) {
|
||||
// //用户名和密码完成校验
|
||||
// session.setAttribute("username", username); //缓存session
|
||||
// session.setAttribute("userid", user.getId()); //缓存session
|
||||
// resultobj.put("username", username);
|
||||
// resultobj.put("msg", "登录成功");
|
||||
// resultobj.put("flag", true);
|
||||
// } else {
|
||||
// //用户名和密码未完成校验
|
||||
// resultobj.put("msg", "用户名或密码错误");
|
||||
// resultobj.put("flag", false);
|
||||
// }
|
||||
// return resultobj.toString();
|
||||
// }
|
||||
|
||||
//登录页
|
||||
@GetMapping("/login")
|
||||
public String login(@RequestParam(value = "error", required = false) String error,
|
||||
@RequestParam(value = "logout", required = false) String logout,Map<String, Object> map) {
|
||||
if (error != null) {
|
||||
map.put("msg", "您输入的用户名密码错误!");
|
||||
return "login";
|
||||
}
|
||||
return resultobj.toString();
|
||||
if (logout != null) {
|
||||
map.put("msg", "退出成功!");
|
||||
return "login";
|
||||
}
|
||||
|
||||
return "login";
|
||||
}
|
||||
|
||||
//退出
|
||||
|
||||
@@ -3,7 +3,9 @@ package com.yaoyuan.jiscuss.entity;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import javax.persistence.Column;
|
||||
import javax.persistence.Entity;
|
||||
@@ -16,6 +18,8 @@ import javax.persistence.Table;
|
||||
|
||||
|
||||
import lombok.Data;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
|
||||
@Data
|
||||
@Entity
|
||||
@@ -66,6 +70,4 @@ public class Users implements Serializable {
|
||||
@Column(name="level")
|
||||
private Integer level;
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
package com.yaoyuan.jiscuss.handler;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.http.HttpStatus;
|
||||
import org.springframework.security.access.AccessDeniedException;
|
||||
import org.springframework.security.web.WebAttributes;
|
||||
import org.springframework.security.web.access.AccessDeniedHandler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
import java.io.PrintWriter;
|
||||
|
||||
/**
|
||||
* 处理无权请求
|
||||
* @author charlie
|
||||
*
|
||||
*/
|
||||
@Component
|
||||
public class CustomAccessDeniedHandler implements AccessDeniedHandler {
|
||||
|
||||
private Logger log = LoggerFactory.getLogger(CustomAccessDeniedHandler.class);
|
||||
|
||||
@Override
|
||||
public void handle(HttpServletRequest request, HttpServletResponse response,
|
||||
AccessDeniedException accessDeniedException) throws IOException, ServletException {
|
||||
boolean isAjax = ControllerTools.isAjaxRequest(request);
|
||||
System.out.println("CustomAccessDeniedHandler handle");
|
||||
if (!response.isCommitted()) {
|
||||
if (isAjax) {
|
||||
String msg = accessDeniedException.getMessage();
|
||||
log.info("accessDeniedException.message:" + msg);
|
||||
String accessDenyMsg = "{\"code\":\"403\",\"msg\":\"没有权限\"}";
|
||||
ControllerTools.print(response, accessDenyMsg);
|
||||
} else {
|
||||
request.setAttribute(WebAttributes.ACCESS_DENIED_403, accessDeniedException);
|
||||
response.setStatus(HttpStatus.FORBIDDEN.value());
|
||||
RequestDispatcher dispatcher = request.getRequestDispatcher("/403");
|
||||
dispatcher.forward(request, response);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public static class ControllerTools {
|
||||
public static boolean isAjaxRequest(HttpServletRequest request) {
|
||||
return "XMLHttpRequest".equals(request.getHeader("X-Requested-With"));
|
||||
}
|
||||
|
||||
public static void print(HttpServletResponse response, String msg) throws IOException {
|
||||
response.setCharacterEncoding("UTF-8");
|
||||
response.setContentType("application/json; charset=utf-8");
|
||||
PrintWriter writer = response.getWriter();
|
||||
writer.write(msg);
|
||||
writer.flush();
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
package com.yaoyuan.jiscuss.handler;
|
||||
|
||||
import org.springframework.security.core.Authentication;
|
||||
import org.springframework.stereotype.Component;
|
||||
import org.springframework.util.AntPathMatcher;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* RBAC数据模型控制权限
|
||||
* @author charlie
|
||||
*
|
||||
*/
|
||||
@Component("rbacPermission")
|
||||
public class RbacPermission{
|
||||
|
||||
private AntPathMatcher antPathMatcher = new AntPathMatcher();
|
||||
|
||||
public boolean hasPermission(HttpServletRequest request, Authentication authentication) {
|
||||
Object principal = authentication.getPrincipal();
|
||||
boolean hasPermission = false;
|
||||
|
||||
hasPermission = true;
|
||||
// if (principal instanceof UserEntity) {
|
||||
// // 读取用户所拥有的权限菜单
|
||||
// List<Menu> menus = ((UserEntity) principal).getRoleMenus();
|
||||
// System.out.println(menus.size());
|
||||
// for (Menu menu : menus) {
|
||||
// if (antPathMatcher.match(menu.getMenuUrl(), request.getRequestURI())) {
|
||||
// hasPermission = true;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
return hasPermission;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
package com.yaoyuan.jiscuss.service.impl;
|
||||
|
||||
import com.yaoyuan.jiscuss.entity.Users;
|
||||
import com.yaoyuan.jiscuss.service.IUsersService;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.security.core.GrantedAuthority;
|
||||
import org.springframework.security.core.authority.SimpleGrantedAuthority;
|
||||
import org.springframework.security.core.userdetails.UserDetails;
|
||||
import org.springframework.security.core.userdetails.User;
|
||||
import org.springframework.security.core.userdetails.UserDetailsService;
|
||||
import org.springframework.security.core.userdetails.UsernameNotFoundException;
|
||||
import org.springframework.security.crypto.password.PasswordEncoder;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author yaoyuan2.chu
|
||||
* @Title:
|
||||
* @Package com.yaoyuan.jiscuss.service.impl
|
||||
* @Description:
|
||||
* @date 2020/7/15 16:34
|
||||
*/
|
||||
@Component
|
||||
public class UserDetailServiceImpl implements UserDetailsService {
|
||||
@Autowired
|
||||
private IUsersService userInfoService;
|
||||
|
||||
/**
|
||||
* 需新建配置类注册一个指定的加密方式Bean,或在下一步Security配置类中注册指定
|
||||
*/
|
||||
@Autowired
|
||||
private PasswordEncoder passwordEncoder;
|
||||
|
||||
@Override
|
||||
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
|
||||
// 通过用户名从数据库获取用户信息
|
||||
Users userInfo = userInfoService.getByUsername(username);
|
||||
if (userInfo == null) {
|
||||
throw new UsernameNotFoundException("用户不存在");
|
||||
}
|
||||
|
||||
// 得到用户角色
|
||||
String role = "admin";
|
||||
|
||||
// 角色集合
|
||||
List<GrantedAuthority> authorities = new ArrayList<>();
|
||||
// 角色必须以`ROLE_`开头,数据库中没有,则在这里加
|
||||
authorities.add(new SimpleGrantedAuthority("ROLE_" + role));
|
||||
|
||||
return new User(
|
||||
userInfo.getUsername(),
|
||||
// 因为数据库是明文,所以这里需加密密码
|
||||
passwordEncoder.encode(userInfo.getPassword()),
|
||||
authorities
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -41,6 +41,8 @@ spring:
|
||||
# 设置ftl文件路径
|
||||
template-loader-path:
|
||||
- classpath:/templates
|
||||
settings:
|
||||
classic_compatible: true
|
||||
# 设置静态文件路径,js,css等
|
||||
mvc:
|
||||
static-path-pattern: /static/**
|
||||
|
||||
@@ -40,7 +40,7 @@ function loginOut() {
|
||||
console.log(data);
|
||||
if(data.flag){
|
||||
$('#userlogin').html('');
|
||||
$('#userlogin').html('<a href="javascript:void(0);" onclick="loginmodel(this)" id="loginmodel">登录 & 注册</a>');
|
||||
$('#userlogin').html('<a href="/login" id="loginmodel">登录 & 注册</a>');
|
||||
window.alert(username + data.msg);
|
||||
username = null;
|
||||
}else{
|
||||
@@ -52,9 +52,3 @@ function loginOut() {
|
||||
}
|
||||
|
||||
|
||||
function loginmodel() {
|
||||
$('.ui.modal.login')
|
||||
.modal('show')
|
||||
;
|
||||
}
|
||||
|
||||
|
||||
@@ -30,53 +30,12 @@
|
||||
<#if username??>
|
||||
${username} <a href="javascript:void(0);" onclick="loginOut(this)" id="loginOut">注销</a>
|
||||
<#else>
|
||||
<a href="javascript:void(0);" onclick="loginmodel(this)" id="loginmodel">登录 & 注册</a>
|
||||
<a href="/login" id="loginmodel">登录 & 注册</a>
|
||||
</#if>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="ui mini modal login">
|
||||
<i class="close icon"></i>
|
||||
|
||||
<div class=" content">
|
||||
<div class="ui middle aligned center aligned grid">
|
||||
<div class="column">
|
||||
<h2 class="ui blue image header">
|
||||
<img src="static/assets/images/logo.png" class="image">
|
||||
<div class="content">
|
||||
登录到账号
|
||||
</div>
|
||||
</h2>
|
||||
<form class="ui large form" id="loginForm">
|
||||
<div class="ui stacked segment">
|
||||
<div class="field">
|
||||
<div class="ui left icon input">
|
||||
<i class="user icon"></i>
|
||||
<input type="text" name="username" placeholder="用户名">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui left icon input">
|
||||
<i class="lock icon"></i>
|
||||
<input type="password" name="password" placeholder="密码">
|
||||
</div>
|
||||
</div>
|
||||
<div class="ui fluid large blue button" id="loginBtn">登录</div>
|
||||
</div>
|
||||
|
||||
<div class="ui error message"></div>
|
||||
|
||||
</form>
|
||||
|
||||
<div class="ui message">
|
||||
新用户? <a href="l#">注册</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" charset="UTF-8" src="/static/js/user/header.js"></script>
|
||||
@@ -0,0 +1,75 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<title>Jiscuss Demo</title>
|
||||
<head>
|
||||
<!-- <link rel="stylesheet" type="text/css" href="static/semanticui/semantic.css"> -->
|
||||
<!-- <script src="static/jquery/jquery-3.4.1.min.js"></script> -->
|
||||
<!-- <script src="static/semanticui/semantic.min.js"></script> -->
|
||||
<link crossorigin="anonymous" integrity="sha384-ATvSpJEmy1egycrmomcFxVn4Z0A6rfjwlzDQrts/1QRerQhR9EEpEYtdysLpQPuQ" href="https://lib.baomitu.com/semantic-ui/2.4.1/semantic.min.css" rel="stylesheet">
|
||||
<link rel="stylesheet" type="text/css" href="/static/semanticui/my.css">
|
||||
<script crossorigin="anonymous" integrity="sha384-vk5WoKIaW/vJyUAd9n/wmopsmNhiy+L2Z+SBxGYnUkunIxVxAv/UtMOhba/xskxh" src="https://lib.baomitu.com/jquery/3.4.1/jquery.min.js"></script>
|
||||
<script crossorigin="anonymous" integrity="sha384-6urqf2sgCGDfIXcoxTUOVIoQV+jFr/Zuc4O2wCRS6Rnd8w0OJ17C4Oo3PuXu8ZtF" src="https://lib.baomitu.com/semantic-ui/2.4.1/semantic.min.js"></script>
|
||||
<script crossorigin="anonymous" integrity="sha384-CpsBIlOAWHuSRRN235sCBzEeKN6hLT6SpOGRkGadKpYj0gDP7+s3Q8pC38z8uGHH" src="https://lib.baomitu.com/tinymce/5.1.1/tinymce.min.js"></script>
|
||||
|
||||
<style type="text/css">
|
||||
body {
|
||||
background-color: #DADADA;
|
||||
}
|
||||
body > .grid {
|
||||
height: 100%;
|
||||
}
|
||||
.image {
|
||||
margin-top: -100px;
|
||||
}
|
||||
.column {
|
||||
max-width: 450px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="ui middle aligned center aligned grid">
|
||||
<div class="column">
|
||||
<h2 class="ui blue image header">
|
||||
<img src="static/assets/images/logo.png" class="image">
|
||||
<div class="content">
|
||||
登录到账号
|
||||
</div>
|
||||
</h2>
|
||||
<form class="ui large form" action="/login" method="post">
|
||||
<input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}"/>
|
||||
<div class="ui stacked segment">
|
||||
<div class="field">
|
||||
<div class="ui left icon input">
|
||||
<i class="user icon"></i>
|
||||
<input type="text" name="username" placeholder="用户名">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui left icon input">
|
||||
<i class="lock icon"></i>
|
||||
<input type="password" name="password" placeholder="密码">
|
||||
</div>
|
||||
</div>
|
||||
<div class="field">
|
||||
<div class="ui pointing red basic label">
|
||||
${msg}
|
||||
</div>
|
||||
</div>
|
||||
<button class="ui fluid large blue button" type="submit">登录</button>
|
||||
</div>
|
||||
|
||||
<div class="ui error message"></div>
|
||||
|
||||
</form>
|
||||
|
||||
<div class="ui message">
|
||||
<a href="/"><——Jiscuss首页</a> 新用户? <a href="login.php#">注册</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
</body>
|
||||
|
||||
</html>
|
||||
Reference in New Issue
Block a user