spring security 1

174 阅读4分钟

基本流程

github.com/cailonghao/…

###maven

<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