1、在pom.xml下<dependencies>添加项目依赖:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-thymeleaf</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2、创建SecurityConfig类并继承WebSecurityConfigurerAdapter类,用于Spring Security 5的配置:
package com.example.testssm.config;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
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.*;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true, prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
/**
* 拦截请求
* 配置Spring Security的Filter链
* @param web
* @throws Exception
*/
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/js/**", "/css/**", "/images/**");
}
/**
* 拦截请求
* 配置如何通过拦截器保护请求
* @param http
* @throws Exception
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login", "/form", "/register", "/register_save", "/regusernameajax", "/druid/**", "/error", "/verifycode")
.permitAll()
.anyRequest()
.authenticated()
.and()
.formLogin()
.loginPage("/login")
.loginProcessingUrl("/form")
.permitAll()
.usernameParameter("username")
.passwordParameter("password")
//.defaultSuccessUrl("/index")
//.successForwardUrl("/index")
//.failureForwardUrl("/error")
.permitAll()
.and()
.logout()
.logoutUrl("/logout")
.deleteCookies()
.clearAuthentication(true)
.invalidateHttpSession(true)
.permitAll()
.and()
.csrf().disable();
}
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
}
3、创建LoginController控制器类,用于用户登录处理:
package com.example.testssm.controller;
import com.example.testssm.dao.LoginUser;
import com.example.testssm.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
@Controller
public class LoginController {
@Autowired
private UserService userService;
@RequestMapping(value = "/login", method = {RequestMethod.GET, RequestMethod.POST})
public String login(Model model){
return "login";
}
@RequestMapping(value = {"/", "/form"}, method = {RequestMethod.GET, RequestMethod.POST})
public String form() {
return "redirect:/index";
}
@GetMapping("/register")
public String register(){
return "register";
}
@PostMapping("/regusernameajax")
@ResponseBody
public String is_exist_name(String username) {
LoginUser loginUser = userService.getUserByName(username);
if(loginUser == null) {
return "false";
}
return "true";
}
@PostMapping("/register_save")
public String registerSave(String username, String password2){
int ret = 0;
if(username.equals("admin")){
ret = userService.insertUserBasic("admin", password2, "admin");
}else{
ret = userService.insertUserBasic(username, password2, "user");
}
if(ret <= 0){
return "register_error";
} else {
return "redirect:/login";
}
}
}
4、创建MainController控制器类,用于登录成功后的页面显示:
package com.example.testssm.controller;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import java.util.Collection;
@Controller
public class MainController {
@RequestMapping(value="/index", method = RequestMethod.GET)
public String index(Model model){
String userName = new String();
Object principal = SecurityContextHolder.getContext().getAuthentication().getPrincipal();
if (principal instanceof UserDetails) {
userName = ((UserDetails) principal).getUsername();
Collection<? extends GrantedAuthority> authorities = ((UserDetails) principal).getAuthorities();
for (GrantedAuthority grantedAuthority : authorities) {
System.out.println("当前用户 " + userName + " 权限 " + grantedAuthority.getAuthority());
}
} else {
userName = "无法获取用户";
}
model.addAttribute("username", userName);
return "index";
}
}
5、创建login.html登录页面,基于thymeleaf模板:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org" xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>登录页面</title>
<link rel="stylesheet" type="text/css" href="./css/login.css">
<link rel="stylesheet" type="text/css" href="./css/Font-Awesome-3.2.1/css/font-awesome.min.css" />
<span th:replace="head_js :: head_jquery"></span>
</head>
<body>
<div id="loginbox">
<div id="loginboxhead"> <span class="icon-user icon-large"></span></div>
<br />
<div class="content">
<span th:if="${param.error}" class="span1">
Invalid username and password.
</span>
<span th:if="${param.logout}" class="span1">
You have been logged out.
</span>
<div id="login_user" style="padding-left: 50px; display: none;"></div>
<form id="formlogin" th:action="@{/form}" method="post" onSubmit="return confirmInput();">
<table>
<tr>
<td class="td1">用户名:</td>
<td class="td2"><input id="username" name="username" type="text" size="30" /></td>
</tr>
<tr>
<td class="td1">密 码:</td>
<td class="td2"><input id="password" name="password" type="password" size="30" /></td>
</tr>
</table>
<table>
<tr>
<td class="td1"><span class="prompt">点击刷新:</span></td>
<td class="td2"><a href="javascript:void(0);" onclick="changecode();">
<img th:src="@{/verifycode}" id="codeImg" width="100px" height="50px" style="border:1px solid #cccccc; vertical-align:middle;" alt="验证码图片,点我换新图" />
</a>
</td>
</tr>
<tr>
<td class="td1">验证码:</td>
<td class="td2"><input id="checkcode" type="text" name="checkcode" disabled="disabled" /></td>
</tr>
</table>
<table>
<tr>
<td class="td3"><input type="submit" value="登 录"/></td>
<td class="td4"><input type="reset" value="重 置" /></td>
<td class="td5"><a th:href="@{/register}"><button type="button">注 册</button></a></td>
</tr>
</table>
</form>
</div>
</div>
<script type="text/javascript" language="javascript">
//生成随机参数
function getRand() {
var mydate = new Date();
var rnd = Math.floor(Math.random() * 9999) + 1;
var result = mydate.getHours().toString() + mydate.getMinutes().toString() + mydate.getSeconds().toString() + rnd;
return result;
}
function changecode(){ // 更换验证码
$('#codeImg').attr("src", "[[@{/}]]verifycode" + "?rnd=" + getRand());
}
//字符串为空
function isNull(str) {
if (str == null || str == "" || str.length < 1)
return true;
else
return false;
}
//在客户端验证用户输入合法性
function confirmInput()
{
if(formlogin.username.value == ''){
alert('请填写您的用户名!');
$('#username').focus();
return false;
}
if(formlogin.password.value == ''){
alert('请填写您的密码!');
$('#password').focus();
return false;
}
return true;
}
window.onload = function(event){
var event = window.event || event;
var loginboxObj = document.getElementById('loginbox');
var posX = document.body.offsetWidth / 2 - loginboxObj.offsetWidth / 2;
loginboxObj.style.left = posX + 'px';
loginboxObj.style.top = '200px';
document.getElementById('loginboxhead').onmousedown = function(event){
var event = window.event || event;
var loginboxObj = document.getElementById('loginbox');
var top = loginboxObj.offsetTop;
var left = loginboxObj.offsetLeft;
var elementX = parseInt(event.clientX - left);
var elementY = parseInt(event.clientY - top);
document.onmousemove = function(event){
var event = window.event || event;
var X = parseInt(event.clientX - elementX);
var Y = parseInt(event.clientY - elementY);
var winW = document.documentElement.clientWidth || document.body.clientWidth;
var winH = document.documentElement.clientHeight || document.body.clientHeight;
var maxW = winW - loginboxObj.offsetWidth;
var maxH = winH - loginboxObj.offsetHeight;
if (X < 0){
X = 0;
} else if(X > maxW){
X = maxW;
}
if (Y < 0){
Y = 0
} else if(Y > maxH){
Y = maxH;
}
loginboxObj.style.left = X + 'px';
loginboxObj.style.top = Y + 'px';
}
}
document.getElementById('loginboxhead').onmouseup = function(event){
document.onmousemove = null;
}
$('#loginboxhead').tooltip({
position: 'top',
content: '<span style="color:#fff">拖动可以移动</span>',
onShow: function(){
$(this).tooltip('tip').css({
backgroundColor: '#666',
borderColor: '#666'
});
}
});
}
</script>
</body>
</html>
6、创建index.html页面,基于thymeleaf模板,用于登录成功后的跳转:
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Index</title>
</head>
<body>
<p th:text="${username}"></p>
<p>主 页</p>
<br />
<a th:href="@{/logout}">退 出</a>
</body>
</html>

本文介绍如何在Spring Boot项目中集成Spring Security进行用户登录认证,包括配置依赖、自定义SecurityConfig、实现登录控制器及页面展示。
1870

被折叠的 条评论
为什么被折叠?



