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<? extends GrantedAuthority> 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