文章目录
功能: 简化用户每次登录都要输入用户名和密码的麻烦,提高用户体验
1、配置类
注意:
一定要添加lazy注解防止依赖循环
@Resource
@Lazy
private UserServiceImpl userService;
@Resource
@Lazy
private PersistentTokenRepository persistentTokenRepository;
package com.atmae.securitydemo.config;
import com.atmae.securitydemo.handle.MyAccessDeniedHandler;
import com.atmae.securitydemo.service.impl.UserServiceImpl;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
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;
import org.springframework.security.web.authentication.rememberme.JdbcTokenRepositoryImpl;
import org.springframework.security.web.authentication.rememberme.PersistentTokenRepository;
import javax.annotation.Resource;
import javax.sql.DataSource;
/**
* @author Mae
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private MyAccessDeniedHandler myAccessDeniedHandler;
@Resource
@Lazy
private UserServiceImpl userService;
@Resource
private DataSource dataSource;
@Resource
@Lazy
private PersistentTokenRepository persistentTokenRepository;
@Bean
public PersistentTokenRepository getPersistentTokenRepository() {
JdbcTokenRepositoryImpl jdbcTokenRepository = new JdbcTokenRepositoryImpl();
/** 自动建表 第一次启动 第二次注释掉即可会报错*/
/** jdbcTokenRepository.setCreateTableOnStartup(true);*/
jdbcTokenRepository.setDataSource(dataSource);
return jdbcTokenRepository;
}
@Bean
public PasswordEncoder getPw() {
return new BCryptPasswordEncoder();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
/** 表单提交*/
http.formLogin()
.usernameParameter("username")
.passwordParameter("password")
/** 当发现/login时 认为是登录 需和表单提交地址相同*/
.loginProcessingUrl("/login")
/** 自定义登录页面*/
.loginPage("/login.html")
/** 成功后执行post请求*/
.successForwardUrl("/index")
/** 失败后执行post请求*/
.failureForwardUrl("/error");
http.authorizeHttpRequests()
/** 放行*/
.antMatchers("/error.html").permitAll()
.antMatchers("/login.html").permitAll()
.antMatchers("/**/*.png").permitAll()
/** 正则表达式*/
.regexMatchers(".+[.]png").permitAll()
/** 权限管理*/
/** .antMatchers("/member.html").hasAnyAuthority("admin")*/
/** 角色判断*/
/** .antMatchers("/member.html").hasRole("student")*/
/** 所有请求都必须被认证*/
.anyRequest().authenticated();
/** 关闭防火墙*/
http.csrf().disable();
/** 异常处理*/
http.exceptionHandling()
.accessDeniedHandler(myAccessDeniedHandler);
/**记住我功能*/
http.rememberMe()
/** 自定义登录逻辑*/
.userDetailsService(userService)
/** 失效时间 60s*/
.tokenValiditySeconds(60)
/** 持久层登录*/
.tokenRepository(persistentTokenRepository);
}
}
2、自定义逻辑
package com.atmae.securitydemo.service.impl;
import com.atmae.securitydemo.mapper.UserMapper;
import com.atmae.securitydemo.pojo.User;
import org.springframework.context.annotation.Lazy;
import org.springframework.security.core.authority.AuthorityUtils;
import org.springframework.security.core.userdetails.UserDetails;
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.Service;
import javax.annotation.Resource;
/**
* @author Mae
*/
@Service
public class UserServiceImpl implements UserDetailsService {
@Resource
private UserMapper userMapper;
@Resource
private PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
/** 查询数据库判断用户名是否存在*/
User user = userMapper.findUserByUsername(username);
System.out.println(user);
if (user == null) {
throw new UsernameNotFoundException("用户名没有找到");
}
/** 把查询出的密码(注册时已经过加密)进行解析,或者直接把密码放入构造方法*/
String password = passwordEncoder.encode(user.getPassword());
return new org.springframework.security.core.userdetails.User(username, password, AuthorityUtils
.commaSeparatedStringToAuthorityList("admin,normal0,ROLE_student0"));
}
}
3、登陆页
记住我的name一定要是 remember-me 否则需要自己配置
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登录页</title>
</head>
<body>
<form action="/login" method="post">
<label for="username">用户名:<input type="text" id="username" name="username" placeholder="请输入用户名"></label><br/>
<label for="password">密码:<input type="password" id="password" name="password" placeholder="请输入密码"></label><br/>
<label for="remember-me">
记住我:
<input id="remember-me" type="checkbox" name="remember-me" value="1"/>
</label><br>
<input type="submit" value="提交">
</form>
</body>
</html>
4、持久层和控制层
package com.atmae.securitydemo.controller;
import org.springframework.security.access.annotation.Secured;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
/**
* @author Mae
*/
@Controller
public class UserController {
@Secured("ROLE_student0")
@PreAuthorize("hasRole('ROLE_student0')") /** 可以不以Role开头*/
@RequestMapping("/index")
public String indexPage() {
return "redirect:index.html";
}
}
package com.atmae.securitydemo.mapper;
import com.atmae.securitydemo.pojo.User;
import org.apache.ibatis.annotations.Mapper;
/**
* @author Mae
*/
@Mapper
public interface UserMapper {
/**
* 根据用户名查询用户
* @param username 用户名
* @return 用户
*/
User findUserByUsername(String username);
}
5、功能
第一次登录
自动生成的数据表
第二次登录直接进入登录页
关闭浏览器直接进入主页则需重新登陆