SpringBoot SpringSecurity 登录、登出自定义与HttpSecurity配置

SpringBoot SpringSecurity 登录、登出自定义与HttpSecurity配置 

  • yml中的变量配置
  ############################ --  认证 -- ############################
security-fig:
  login-url:  /login
  login-processing-url: /loginProcess
  error-url:  /loginFail
  logout-url: /signout
  swagger-url:  /doc
  • HttpSecurity配置 
package com.config.security;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
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.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UserDetailsService;

/**
 * Security fig
 */
@Slf4j
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true,prePostEnabled = true)//开启方法控制注解 @Secured、@PreAuthorize、@PostAuthorize
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {

    @Value( "${security-fig.login-url}" )
    private String loginUrl;
    @Value( "${security-fig.login-processing-url}" )
    private String loginProcessingUrl;
    @Value( "${security-fig.error-url}" )
    private String errorUrl;
    @Value( "${security-fig.logout-url}" )
    private String logoutUrl;

    @Autowired
    private CustomLogoutService customLogoutService;

    @Bean
    UserDetailsService customUserService(){
        return new CustomLoginService();
    }


    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
                .portMapper(  )
                .http( 80 )
                .mapsTo( 443 )
                .and()
                .authorizeRequests()//登录配置
                .antMatchers( "/sys/**" ).permitAll()//允许访问匹配的路径
                .antMatchers( "/public/**" ).permitAll()
                .antMatchers( "/static/**" ).permitAll()
                .antMatchers( "/templates/**" ).permitAll()
                .anyRequest().authenticated()//以上配置除外,其它需要认证
                .and()
                .csrf().disable()//关闭post限制
                .formLogin()
                .loginPage( loginUrl )//登录页面
                .loginProcessingUrl(loginProcessingUrl)//登录action 提交地址
//                .defaultSuccessUrl( "/index.html" )//这里指定的是静态页面,必须加后缀,如果不指定,就走路径为“/”的方法
//                .failureUrl( "/login?error" )
                .failureUrl(errorUrl)//登录失败处理方法
                .permitAll()
                .and()
                .logout()//登出配置
                .logoutUrl(logoutUrl)
                .deleteCookies("JSESSIONID")//登出清理cookie
                .logoutSuccessHandler( customLogoutService )//登出实现类
                .permitAll();
    }

    @Override
    public void configure(WebSecurity web) throws Exception {
        //设置静态资源不要拦截
        web.ignoring().antMatchers( "/public/**","/static/**","/templates/**");
    }

    @Autowired
    private SecurityAuthenticationProvider provider;//注入我们自己的AuthenticationProvider

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //走默认认证
//        auth.userDetailsService( customUserService() ).passwordEncoder( new PasswordConfig() );
        //走自定义认证
        auth.authenticationProvider(provider);
    }


@Autowired
    private SecurityAuthenticationProvider provider;//注入我们自己的AuthenticationProvider

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //走默认认证
//        auth.userDetailsService( customUserService() ).passwordEncoder( new PasswordConfig() );
        //走自定义认证
        auth.authenticationProvider(provider);


}
  • 登录逻辑实现类
package com.config.security;


import java.util.Collection;
import java.util.Date;

import com.ll.admin.dao.LoginRepository;
import com.ll.admin.domain.Login;
import com.utils.EncryptionUtil;
import com.utils.MD5;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.AuthenticationProvider;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.stereotype.Component;


/**
 * 登录逻辑实现
 */
@Component
@Slf4j
public class SecurityAuthenticationProvider implements AuthenticationProvider {

    @Autowired
    private UserDetailsService userDetailService;
    @Autowired
    private LoginRepository loginRepository;

    @Override
    public Authentication authenticate(Authentication authentication) throws AuthenticationException {

        WebAuthenticationDetails details =(WebAuthenticationDetails) authentication.getDetails();
        String remoteAddress = details.getRemoteAddress();
        remoteAddress = "0:0:0:0:0:0:0:1".equals( remoteAddress ) ? "127.0.0.1" : remoteAddress; //访问IP
        String userName = authentication.getName();	// 这个获取表单输入中返回的用户名;
        String password = authentication.getCredentials().toString();	// 这个是表单中输入的密码;
        Login loginData = (Login) userDetailService.loadUserByUsername(userName);
Collection authorities = loginData.getAuthorities();
        // 构建返回的用户登录成功的token

        return new UsernamePasswordAuthenticationToken(loginData, password, authorities);
    }

    @Override
    public boolean supports(Class authentication) {
        // TODO Auto-generated method stub
        // 这里直接改成retrun true;表示是支持这个执行
        return true;
    }
}
  • 登出逻辑实现
package com.config.security;

import com.ll.admin.dao.LoginRepository;
import com.ll.admin.domain.Login;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.core.Authentication;
import org.springframework.security.web.authentication.WebAuthenticationDetails;
import org.springframework.security.web.authentication.logout.LogoutSuccessHandler;
import org.springframework.stereotype.Component;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.Date;

/**
 * 登出
 * 默认被 /signout 请求
 */
@Slf4j
@Component
public class CustomLogoutService implements LogoutSuccessHandler {

    @Value( "${server.servlet.context-path}" )
    private String contextPath;
    @Value( "${security-fig.login-url}" )
    private String loginUrl;

    @Autowired
    private LoginRepository loginRepository;

    @Override
    public void onLogoutSuccess(HttpServletRequest request,
                                HttpServletResponse response,
                                Authentication authentication)
            throws IOException, ServletException {

        //默认被 /signout 请求,这里写登出前要做的事 
        response.sendRedirect( contextPath + loginUrl );
    }
}
  •  成功与错误跳转
  • Controller 用
    @AuthenticationPrincipal UserDetails userDetails 获取当前用户信息
  • 也可以在session中提取当前用户信息
    HttpSession session = request.getSession();
    SecurityContextImpl ssc = (SecurityContextImpl) session.getAttribute( "SPRING_SECURITY_CONTEXT" );
    Authentication authentication = ssc.getAuthentication();
    Login details =(Login) authentication.getPrincipal();
  • 错误跳转中 运用session获取异常信息
  • HttpSession session = request.getSession();
    Object badCredentialsException = session.getAttribute( "SPRING_SECURITY_LAST_EXCEPTION" );
package com.config.security;

import com.ll.admin.dto.Msg;
import lombok.extern.slf4j.Slf4j;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

/**
 * 登录跳转配置
 */
@Slf4j
@Controller
public class RequestController {

    /**
     * 成功首页
     * @param userDetails
     * @param model
     * @return
     */
    @RequestMapping("/")
    public String index (@AuthenticationPrincipal UserDetails userDetails, Model model){
        Msg msg = new Msg( "测试标题", "测试内容", "额外信息,只有管理员可以看到!" );
        model.addAttribute( "msg",msg );
        return "index";
    }

    /**
     * 登录失败返回接口
     * @param request
     * @param model
     * @return
     */
    @RequestMapping("/loginFail")
    public String loginFail (HttpServletRequest request, Model model){
        HttpSession session = request.getSession();
        Object badCredentialsException = session.getAttribute( "SPRING_SECURITY_LAST_EXCEPTION" );
        String badCredentialsExceptionStr = badCredentialsException.toString();
        String msg = badCredentialsExceptionStr.split( ":" )[1];
        //错误消息提示
        model.addAttribute( "msg",msg);
        return "login";
    }


}

随笔记录,方便学习

2020-07-03

 

你可能感兴趣的:(安全与认证)