关键部分
<dependency>
<groupId>org.springframework.securitygroupId>
<artifactId>spring-security-webartifactId>
<version>5.5.1version>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-securityartifactId>
<version>RELEASEversion>
<scope>compilescope>
dependency>
补充部分
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-thymeleafartifactId>
dependency>
<dependency>
<groupId>com.google.code.gsongroupId>
<artifactId>gsonartifactId>
<version>2.8.2version>
dependency>
<dependency>
<groupId>org.apache.commonsgroupId>
<artifactId>commons-lang3artifactId>
dependency>
<dependency>
<groupId>org.projectlombokgroupId>
<artifactId>lombokartifactId>
<optional>trueoptional>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.1.2version>
dependency>
<dependency>
<groupId>mysqlgroupId>
<artifactId>mysql-connector-javaartifactId>
<scope>runtimescope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-testartifactId>
<scope>testscope>
dependency>
<dependency>
<groupId>org.springframework.bootgroupId>
<artifactId>spring-boot-starter-webartifactId>
dependency>
<dependency>
<groupId>org.mybatis.spring.bootgroupId>
<artifactId>mybatis-spring-boot-starterartifactId>
<version>2.2.0version>
dependency>
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private UserService userService;
/**
* 未登录
*/
@Resource
private AuthenticationEntry authenticationEntry ;
/**
* 登录成功
*/
@Resource
private AuthenticationSuccess authenticationSuccess;
/**
* 登录失败
*/
@Resource
private AuthenticationFailure authenticationFailure;
/**
* 无权访问
*/
@Resource
private AccessDenied accessDenied ;
/**
* 注销操作
*/
@Resource
private LogoutSuccess logoutSuccess ;
/**
* 异地登录,账号下线时的逻辑处理
*/
@Resource
private SessionInformationExpiredStrategy sessionInformationExpiredStrategy;
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(userService)
.passwordEncoder(new BCryptPasswordEncoder());
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//cors()解决跨域问题,csrf()会与restful风格冲突,默认 springsecurity 是开启的,所以要disable()关闭一下
http.cors().and().csrf().disable();
http.authorizeRequests()
.antMatchers("/add").permitAll()
.antMatchers("/test").hasRole("ADMIN")
// hasRole会将参数自动加上ROLE_
.and()
//开启登录
.formLogin()
.usernameParameter("username")
.passwordParameter("password")
.loginPage("/toLogin")
.loginProcessingUrl("/login")
//允许所有人访问
.permitAll()
// 登录成功逻辑处理
.successHandler(authenticationSuccess)
// 登录失败逻辑处理
.failureHandler(authenticationFailure)
.and()
//开启注销
.logout()
//允许所有人访问
.permitAll()
//注销逻辑处理
.logoutSuccessHandler(logoutSuccess)
//删除cookie
.deleteCookies("JSESSIONID")
.and().exceptionHandling()
//权限不足的时候的逻辑处理
.accessDeniedHandler(accessDenied)
//未登录是的逻辑处理
.authenticationEntryPoint(authenticationEntry)
.and()
.sessionManagement()
//最多只能一个用户登录一个账号
.maximumSessions(1)
//异地登录,账号下线时的逻辑处理
.expiredSessionStrategy(sessionInformationExpiredStrategy);
}
@Override
public void configure(WebSecurity web) throws Exception {
super.configure(web);
}
}
/**
* 未登录时
* @author CH
* @date 2021-08-19 15:23
*/
@Component
public class AuthenticationEntry implements AuthenticationEntryPoint {
@Autowired
Gson gson;
/**
* 未登录时返回给前端数据
*/
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, IOException {
Result<Object> result = ResultUtil.error(401,"需要登录!!");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(gson.toJson(result));
}
}
/**
* 登录成功后自定义操作
* @author CH
* @date 2021-08-19 16:23
*/
@Component
public class AuthenticationSuccess implements AuthenticationSuccessHandler {
@Autowired
Gson gson;
@Override
public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException, IOException {
//登录成功时返回给前端的数据
Result<Object> result = ResultUtil.success("登录成功!!!!!");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(gson.toJson(result));
}
}
/**
* 登录失败
* @author CH
* @date 2021-08-19 16:20
*/
@Component
public class AuthenticationFailure implements AuthenticationFailureHandler {
@Autowired
Gson gson;
@Override
public void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response, AuthenticationException e) throws IOException, IOException {
Result<Object> result;
if (e instanceof UsernameNotFoundException) {
result = ResultUtil.error(-1,e.getMessage());
} else if (e instanceof BadCredentialsException) {
result = ResultUtil.error(-1,"密码错误!!");
} else {
result = ResultUtil.error(-1,e.getMessage());
}
//处理编码方式,防止中文乱码的情况
response.setContentType("text/json;charset=utf-8");
//返回给前台
response.getWriter().write(gson.toJson(result));
}
}
/**
* 无权访问
* @author CH
* @date 2021-08-19 16:25
*/
@Component
public class AccessDenied implements AccessDeniedHandler {
@Autowired
Gson gson;
@Override
public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException e) throws IOException {
Result<Object> result = ResultUtil.error(-1,"无权访问,need Authorities!!");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(gson.toJson(result));
}
}
/**
* 注销操作
* @author CH
* @date 2021-08-19 17:12
*/
@Component
public class LogoutSuccess implements LogoutSuccessHandler {
@Autowired
Gson gson;
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
Result<Object> result = ResultUtil.success("注销成功");
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(gson.toJson(result));
}
}
/**
* 异地登录,账号下线时的逻辑处理
* @author CH
* @date 2021-08-19 17:06
*/
@Component
public class SessionInformationExpiredStrategy implements org.springframework.security.web.session.SessionInformationExpiredStrategy {
@Autowired
Gson gson;
@Override
public void onExpiredSessionDetected(SessionInformationExpiredEvent event) throws IOException, ServletException {
Result<Object> result = ResultUtil.error(-1,"您的账号在异地登录,建议修改密码");
HttpServletResponse response = event.getResponse();
response.setContentType("application/json;charset=utf-8");
response.getWriter().write(gson.toJson(result));
}
}
/**
* @author CH
* @date 2021-08-19 11:13
*/
@RestController
public class UserController {
@Autowired
private UserService userService;
@RequestMapping("/test")
public String index(){
return "首页---->"+LocalDateTime.now().toString();
}
@RequestMapping("/add")
public String add() {
User user = new User();
user.setUsername("user1");
user.setPassword("123456");
user.setState(0);
user.setRoleId(1);
userService.add(user);
return "添加用户---->"+LocalDateTime.now().toString();
}
@RequestMapping("ttt")
public String ttt(){
return "TTTT";
}
}
需要继承UserDetailsService类
public interface UserService extends UserDetailsService {
@Override
UserDetails loadUserByUsername(String username);
int add(User user);
}
/**
* @author CH
* @date 2021-08-19 10:48
*/
@Service
public class UserServiceImpl implements UserService, UserDetailsService {
@Autowired
private UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) {
//自己写的查询
UserDto userDto = userMapper.queryUserByUserName(username);
if (username == null) {
throw new UsernameNotFoundException("用户名不存在");
}
List<SimpleGrantedAuthority> authorityList = new ArrayList<>();
String role = userDto.getCode();
if (StringUtils.isNotBlank(role)) {
authorityList.add(new SimpleGrantedAuthority(role.trim()));
}
//结尾返回org.springframework.security.core.userdetails.User!!
return new org.springframework.security.core.userdetails
.User(userDto.getUsername(), userDto.getPassword(), authorityList);
}
@Override
public int add(User user) {
user.setPassword(new BCryptPasswordEncoder().encode(user.getPassword()));
return userMapper.add(user);
}
}
@Mapper
public interface UserMapper {
//自己写一下查询
UserDto queryUserByUserName(String username);
int add(User user);
}
server:
port: 8000
spring:
datasource:
username: root
password: 123456
url: jdbc:mysql://localhost:3306/ch_pf?useUnicode=true&characterEncoding=utf-8
driver-class-name: com.mysql.cj.jdbc.Driver
thymeleaf:
prefix: classpath:/templates/
cache: false
suffix: .html
mode: LEGACYHTML5
template-resolver-order: 0
mybatis:
mapper-locations: classpath:mapper/*Mapper.xml
type-aliases-package: com.website.entity
DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org"
xmlns:sec="http://www.thymeleaf.org/extras/spring-security">
<head>
<meta charset="UTF-8">
<title>登录title>
head>
<body>
<form th:action="@{/login}" method="post">
<input type="text" value="" name="username">
<input type="password" value="" name="password">
<input type="submit" value="提交">
form>
body>
html>
/**
* MVC配置
* @author CH
* @date 2021-08-19 11:45
*/
@Configuration
public class WebMvcConfig implements WebMvcConfigurer {
@Override
public void addViewControllers(ViewControllerRegistry registry) {
registry.addViewController("/toLogin").setViewName("login");
}
}