springsecurity
新建springboot项目
1.导入依赖
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-boot-starter</artifactId>
<version>3.0.5</version>
</dependency>
<dependency>
<groupId>org.thymeleaf</groupId>
<artifactId>thymeleaf-spring5</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
</dependency>
<dependency>
<groupId>org.thymeleaf.extras</groupId>
<artifactId>thymeleaf-extras-java8time</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
</dependencies>
2.application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/textnode?serverTimeZone=UTC&useUnicode=true&characterEncoding=UTF-8
spring.datasource.username=root
spring.datasource.password=root
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
3. entity层
//和数据库字段一样
@Data
@TableName("tian")
public class UserLogin {
@TableId(type = IdType.AUTO)
private int id;
private String name;
private String password;
}
4.dao层
@Mapper
@Repository
public interface UserMapper extends BaseMapper<UserLogin> {
}
5.service层
public interface UserService extends IService<UserLogin> {
}
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, UserLogin> implements UserService {
}
6.controller层
package com.example.springsecuritydemo.controller;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@Controller
public class LoginController {
// @RequestMapping("/login")
// public String login(){
// return "redirect:main.html";
// }
@RequestMapping("/toMain")
public String toMain(){
return "redirect:main.html";
}
@RequestMapping("/toError")
public String toError(){
return "redirect:error.html";
}
}
config
package com.example.springsecuritydemo.config;
import com.example.springsecuritydemo.handle.MyAuthenticationFailHandle;
import com.example.springsecuritydemo.handle.MyAuthenticationSuccessHandle;
import com.example.springsecuritydemo.service.UserDetailServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
private UserDetailServiceImpl userDetailService;
/*
// 没有加此段代码 数据库密码如果是明文,UserDetailServiceImpl传入的明文密码登录不进去,加了就可以或者 UserDetailServiceImpl传入的密码是经过加密返回User对象就可以登录成功
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailService).passwordEncoder(getPw()); //注释掉原本从内存中加载用户的代码。 }
}
*/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
// .usernameParameter("username123")//自定义入参和前端的name属性一样
// .passwordParameter("password123")//自定义入参
.loginPage("/login.html") //自定义登录页面
.loginProcessingUrl("/login")//必须和表单提交的接口一样,回去执行自定义登录逻辑
// .successForwardUrl("/toMain")//登录成功后跳转的页面 POST请求
//前后端分离 跳转不归我们管 编写handle.MyAuthenticationSuccessHandle
.successHandler(new MyAuthenticationSuccessHandle("http://www.baidu.com"))
// .failureForwardUrl("/toError") //登录失败后跳转的页面 POST请求
.failureHandler(new MyAuthenticationFailHandle("/error.html"))//自定义登陆失败处理器
;
//授权
http.authorizeRequests()
.antMatchers("/login.html").permitAll()
.antMatchers("/error.html").permitAll()
//拦截所有请求
.anyRequest().authenticated();
//防止网站攻击
http.csrf().disable();//登录失败可能存在的原因
}
@Bean
public PasswordEncoder getPw() {
return new BCryptPasswordEncoder();
}
}
UserDetailServiceImpl
package com.example.springsecuritydemo.service;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.example.springsecuritydemo.entity.UserLogin;
import com.example.springsecuritydemo.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.*;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.stereotype.Service;
@Service
public class UserDetailServiceImpl implements UserDetailsService{
// @Autowired
// UserService service;
@Autowired
UserMapper mapper;
@Autowired
PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
QueryWrapper<UserLogin> wrapper = new QueryWrapper<>();
wrapper.eq("name",username);
UserLogin one = mapper.selectOne(wrapper);
if(one==null){
throw new UsernameNotFoundException("用户名不存在");
}
// String password = passwordEncoder.encode(one.getPassword()); //加密后传入
// System.out.println(password);
return new User(username,one.getPassword(), AuthorityUtils.commaSeparatedStringToAuthorityList("admin,normal"));
}
}
handle/MyAuthenticationFailHandle
package com.example.springsecuritydemo.handle;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.web.authentication.AuthenticationFailureHandler;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyAuthenticationFailHandle implements AuthenticationFailureHandler {
private String url;
public MyAuthenticationFailHandle(String url) {
this.url = url;
}
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException exception) throws IOException, ServletException {
response.sendRedirect(url);
}
}
handle/MyAuthenticationSuccessHandle
package com.example.springsecuritydemo.handle;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.AuthenticationSuccessHandler;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class MyAuthenticationSuccessHandle implements AuthenticationSuccessHandler {
private String url;
public MyAuthenticationSuccessHandle(String url) {
this.url = url;
}
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.sendRedirect(url);
}
}
前端static/login.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
<form action="/login" method="post">
<!-- 注意name属性必须是 username 可以后端改-->
用户名 : <input type="text" name="username">
<!-- 注意name属性必须是 password -->
密码 : <input type="password" name="password">
<input type="submit" value="登录">
</form>
</body>
</html>
error.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
登陆失败
<a href="/login.html">跳到登陆页面</a>
</body>
</html>
main.html
<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Title</title>
</head>
<body>
登录成功
</body>
</html>