基本流程
github.com/cailonghao/…

<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>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
AuthenticationManager/ProviderManager
ProviderManager 是AuthenticationManager的一个实现,ProviderManager维护一份提供认证的AuthenticationProvider列表,有一个认证成功就认为登陆成功

AuthenticationProvider提供具体的认证逻辑,常用的DaoAuthenticationProvider提供密码比对,账号过期/检查之类的功能
(密码比对) 抛出AuthenticationException即认证失败

重写WebSecurityConfigurerAdapter类的相关方法,实现自己的逻辑
默认的未登录请求/登出会302跳到登陆页面,需要重写相关返回的方法,同时可以自定义登录成功/失败/权限不足的返回数据,
@EnableWebSecurity
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true) #权限注解
public class SecurityConfig extends WebSecurityConfigurerAdapter {}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginProcessingUrl("/login") #登录
.usernameParameter("email") #参数1
.passwordParameter("password") #参数2
.successForwardUrl("/loginSuccess") #登录成功
.failureForwardUrl("/loginFail").permitAll() #登录失败
.and()
.logout()
.logoutSuccessHandler(new LogoutSuccService()) #登出
.and()
.exceptionHandling()
.accessDeniedPage("/access") #权限不足
.authenticationEntryPoint(new NoLoginService("noLogin")) #未登录发访问
.and()
.sessionManagement()
.sessionCreationPolicy(SessionCreationPolicy.IF_REQUIRED)
.and()
.authorizeRequests()
.anyRequest().authenticated()
.and()
.httpBasic().disable()
.csrf().disable();
}
DaoAuthenticationProviderke需要提供一个获取用户的的方法,配合一个加密方法
@Autowired
LoadUserService loadUserService;
@Bean
PasswordEncoder passwordEncoder() {
return new BCryptPasswordEncoder();
}
@Override
protected UserDetailsService userDetailsService() {
return loadUserService;
}
@Slf4j
@Service
public class LoadUserService implements UserDetailsService {
@Autowired
PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
log.info("email->{}",s);
String password = passwordEncoder.encode("123456");
return new Person("calilonghao1234@foxmail.com",password,"ROLE_USER","ROLE_ADMIN");
}
}
未登录的处理
@Slf4j
public class NoLoginService extends LoginUrlAuthenticationEntryPoint {
public NoLoginService(String loginFormUrl) {
super(loginFormUrl);
}
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException {
log.info("未登录请求");
String loginForm = this.determineUrlToUseForThisRequest(request, response, authException);
RequestDispatcher dispatcher = request.getRequestDispatcher(loginForm);
dispatcher.forward(request, response);
}
}
登出
@Slf4j
public class LogoutSuccService extends SimpleUrlLogoutSuccessHandler {
public LogoutSuccService() {
super.setDefaultTargetUrl("/logout");
}
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
log.info("登出成功");
String targetUrl = this.determineTargetUrl(request, response, authentication);
RequestDispatcher dispatcher = request.getRequestDispatcher(targetUrl);
dispatcher.forward(request, response);
}
}
自定义的逻辑都转到相应接口处理
package com.simple.controller;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* @author cainiao
* @program: spring-securiy
* @description:
* @create: 2020-06-12 16:13
**/
@Slf4j
@RestController
public class IndexController {
/**
* @exception:
* @DESP: 未登录
* @Date: 2020/6/12 cai
*/
@RequestMapping("/noLogin")
public Map<String,Object> noLogin(HttpServletRequest request){
Map<String,Object> map = new HashMap<>();
map.put("msg","登陆啊大哥");
map.put("uri",request.getRequestURI());
return map;
}
/**
* @exception:
* @DESP: 登录成功
* @Date: 2020/6/12 cai
*/
@RequestMapping("/loginSuccess")
public Map<String,Object> succ(HttpServletRequest request){
Map<String,Object> map = new HashMap<>();
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String email =authentication.getName();
List<GrantedAuthority> list = (List<GrantedAuthority>) authentication.getAuthorities();
map.put("email",email);
map.put("role",list);
map.put("uri",request.getRequestURI());
return map;
}
/**
* @exception:
* @DESP: 登陆失败
* @Date: 2020/6/12 cai
*/
@RequestMapping("/loginFail")
public Map<String,Object> err(HttpServletRequest request){
AuthenticationException exception = (AuthenticationException) request.getAttribute("SPRING_SECURITY_LAST_EXCEPTION");
Map<String,Object> map = new HashMap<>();
map.put("error",exception.getMessage());
map.put("uri",request.getRequestURI());
return map;
}
/**
* @exception:
* @DESP: 权限不足
* @Date: 2020/6/12 cai
*/
@RequestMapping("/access")
public Map<String,Object> access(HttpServletRequest request){
AccessDeniedException exception = (AccessDeniedException) request.getAttribute("SPRING_SECURITY_403_EXCEPTION");
Map<String,Object> map = new HashMap<>();
map.put("error",exception.getMessage());
map.put("uri",request.getRequestURI());
return map;
}
/**
* @exception:
* @DESP: 测试权限
* @Date: 2020/6/12 cai
*/
@PreAuthorize("hasRole('USER')")
@RequestMapping("/user")
public Map<String,Object> user(HttpServletRequest request){
Map<String,Object> map = new HashMap<>();
map.put("msg","user");
map.put("uri",request.getRequestURI());
return map;
}
/**
* @exception:
* @DESP: 测试权限
* @Date: 2020/6/12 cai
*/
@PreAuthorize("hasAnyRole('ADMIN')")
@RequestMapping("/admin")
public Map<String,Object> admin(HttpServletRequest request){
Map<String,Object> map = new HashMap<>();
map.put("msg","admin");
map.put("uri",request.getRequestURI());
return map;
}
/**
* @exception:
* @DESP: 测试权限
* @Date: 2020/6/12 cai
*/
@PreAuthorize("hasRole('info')")
@RequestMapping("/info")
public Map<String,Object> info(HttpServletRequest request){
Map<String,Object> map = new HashMap<>();
map.put("msg","info");
map.put("uri",request.getRequestURI());
return map;
}
/**
* @exception:
* @DESP: 测试登出
* @Date: 2020/6/12 cai
*/
@RequestMapping("/logout")
public Map<String,Object> logout(HttpServletRequest request){
Map<String,Object> map = new HashMap<>();
map.put("msg","info");
map.put("uri",request.getRequestURI());
return map;
}
}
测试路径 (idea下新建http文件测试)
### Send POST request with body as parameters
POST http://localhost:34000/login
Content-Type: application/x-www-form-urlencoded
email=cailonghao1234@foxmail.com&password=123456
### Send POST request with body as parameters
POST http://localhost:34000/login
Content-Type: application/x-www-form-urlencoded
email=cailonghao1234@foxmail.com&password=1234567
### Send POST request with body as parameters
POST http://localhost:34000/user
Content-Type: application/x-www-form-urlencoded
### Send POST request with body as parameters
POST http://localhost:34000/admin
Content-Type: application/x-www-form-urlencoded
### Send POST request with body as parameters
POST http://localhost:34000/info
Content-Type: application/x-www-form-urlencoded
### Send POST request with body as parameters
POST http://localhost:34000/logout
Content-Type: application/x-www-form-urlencoded