日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

spring security认证

發布時間:2023/12/10 编程问答 24 豆豆
生活随笔 收集整理的這篇文章主要介紹了 spring security认证 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1 開發基于表單的認證

Spring security核心的功能

  • 認證(你是誰?)
  • 授權(你能干什么?)
  • 攻擊防護(防止偽造身份)

spring security實現了默認的用戶名+密碼認證,默認用戶名為user,密碼為:

?

?

?spring security基本原理:過濾器鏈

?

?  對于UsernamePasswordAuthenticationFilter只會攔截 url為/login,method為POST的請求。

?1.1 自定義用戶認證邏輯

1)處理用戶信息獲取邏輯

  UserDetailsService接口,只有一個方法:loadUserByUsername

實現該接口:數據庫中存放的是加密密碼,對于同一個密碼不同時間的加密密文不一樣

@Component public class MyUserDetailsService implements UserDetailsService {private Logger logger = LoggerFactory.getLogger(getClass());@Autowiredprivate PasswordEncoder passwordEncoder;@Overridepublic UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {logger.info("用戶名信息:" + s);// 根據用戶名查找用戶信息logger.info("數據庫密碼:" + passwordEncoder.encode("123456"));// 用戶名和密碼信息用來做認證,權限信息用來對該用戶做授權return new User(s, "$2a$10$eFw06n0ABK2NFuse8y5f/eDUq7we26qQTceEtXSWNbMXnQ5Yf5Iha",AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));} }

?

?

2)處理用戶信息校驗邏輯

?

  處理密碼加密解密:在配置文件中將PasswordEncoder對象注入spring容器,等價于@Component+包掃描組件

?

?

1.2 個性化用戶認證流程

1)對于瀏覽器,返回自定義登錄頁面,讓UsernamePasswordXxxFilter來處理登錄請求;對于調用RESTful服務,返回json錯誤信息。

 ? 用戶登錄成功后 ,對于瀏覽器,返回需要的頁面;對于服務,返回json數據。

?

?  權限配置:

@Overrideprotected void configure(HttpSecurity http) throws Exception {http.formLogin()// 表單登錄.loginPage("/authentication/require") //將登錄頁面重定向到controller.loginProcessingUrl("/authentication/form").and().authorizeRequests() //請求授權.antMatchers("/authentication/require",securityProperties.getBrowser().getLoginPage()).permitAll()//該頁面允許通過 .anyRequest().authenticated() // 其他資源需要認證 .and().csrf().disable(); // 將跨站防護關掉}

?

  

  控制器,根據之前URL的路徑判斷是否為RESTful服務,在處理

/* 當客戶端發出請求,當需要認證時,spring security會重定向到該控制器*/ @RestController public class BrowserSecurityController {private Logger logger = LoggerFactory.getLogger(getClass());// 請求緩存private RequestCache requestCache = new HttpSessionRequestCache();private RedirectStrategy redirectStrategy = new DefaultRedirectStrategy();@Autowiredprivate SecurityProperties securityProperties;/*** 當需要身份認證時跳轉到這里* @param request* @param response* @return*/@RequestMapping("/authentication/require")@ResponseStatus(code = HttpStatus.UNAUTHORIZED)public SimpleResponse requireAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException {// 判斷請求類型,HTML或者appSavedRequest savedRequest = requestCache.getRequest(request, response);if(savedRequest!=null){String targetUrl = savedRequest.getRedirectUrl();logger.info("引發跳轉的URL:"+targetUrl);// 如果之前的URL為.html結尾的URL,則重定向到登錄頁面if(StringUtils.endsWithIgnoreCase(targetUrl, ".html")){redirectStrategy.sendRedirect(request, response,securityProperties.getBrowser().getLoginPage());}}return new SimpleResponse("請求的服務需要身份認證,請引導用戶到登錄頁面");} } BrowserSecurityController.java

?

?

  在啟動項目中的application.properties文件中配置登錄頁面:

# 配置登錄頁面 getword.security.browser.loginPage=/demo.html

?

?

  讀取配置文件信息:

  

import org.springframework.boot.context.properties.ConfigurationProperties;// 讀取前綴為getword.security的屬性配置,其中browser中的屬性會被讀取到browserProperties中 @ConfigurationProperties(prefix = "getword.security") public class SecurityProperties {// browser的屬性會匹配getword.security.browser后面的屬性private BrowserProperties browser = new BrowserProperties();public BrowserProperties getBrowser() {return browser;}public void setBrowser(BrowserProperties browser) {this.browser = browser;} } SecurityProperties.java

?

?

public class BrowserProperties {private String loginPage = "/login.html"; //默認值public String getLoginPage() {return loginPage;}public void setLoginPage(String loginPage) {this.loginPage = loginPage;} } BrowserProperties.java

?

?

@Configuration @EnableConfigurationProperties(SecurityProperties.class) //讓屬性配置讀取器生效 public class SecurityCodeConfig { }

?

?

2)自定義登錄成功處理,異步登錄,AuthenticationSuccessHandler接口

  自定義登錄成處理:

@Component("vstudyAuthenticationSuccessHandler") public class VstudyAuthenticationSuccessHandler implements AuthenticationSuccessHandler {private Logger logger = LoggerFactory.getLogger(getClass());//工具類, 將對象轉成json @Autowiredprivate ObjectMapper objectMapper;// 登錄成功后調用 @Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {logger.info("登錄成功");response.setContentType("application/json;charset=utf-8");response.getWriter().write(objectMapper.writeValueAsString(authentication));} } VstudyAuthenticationSuccessHandler

  注冊,使處理器生效:

?

?

3)登錄失敗處理

@Component("vstudyAuthenticationFailHandler") public class VstudyAuthenticationFailHandler implements AuthenticationFailureHandler {@Autowiredprivate ObjectMapper objectMapper;private Logger logger = LoggerFactory.getLogger(getClass());@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,AuthenticationException e) throws IOException, ServletException {logger.info("登錄失敗");response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); //服務器內部錯誤response.setContentType("application/json;charset=utf-8");response.getWriter().write(objectMapper.writeValueAsString(e));} } VstudyAuthenticationFailHandler.java

?

配置:和success類似

?

4)判斷請求方式,做出相應的處理

successHandler:

@Component("vstudyAuthenticationSuccessHandler") public class VstudyAuthenticationSuccessHandler extends SavedRequestAwareAuthenticationSuccessHandler {private Logger logger = LoggerFactory.getLogger(getClass());//工具類, 將對象轉成json @Autowiredprivate ObjectMapper objectMapper;@Autowiredprivate SecurityProperties securityProperties; //獲取配置信息// 登錄成功后調用 @Overridepublic void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException {logger.info("登錄成功");if(LoginType.JSON.equals(securityProperties.getBrowser().getLoginType())){response.setContentType("application/json;charset=utf-8");response.getWriter().write(objectMapper.writeValueAsString(authentication));}else{// 調用父類方法,完成重定向跳轉super.onAuthenticationSuccess(request, response, authentication);}} } VstudyAuthenticationSuccessHandler

?

failureHandler:

@Component("vstudyAuthenticationFailHandler") public class VstudyAuthenticationFailHandler extends SimpleUrlAuthenticationFailureHandler {@Autowiredprivate SecurityProperties securityProperties;@Autowiredprivate ObjectMapper objectMapper;private Logger logger = LoggerFactory.getLogger(getClass());@Overridepublic void onAuthenticationFailure(HttpServletRequest request, HttpServletResponse response,AuthenticationException e) throws IOException, ServletException {logger.info("登錄失敗");if(LoginType.JSON.equals(securityProperties.getBrowser().getLoginType())){response.setStatus(HttpStatus.INTERNAL_SERVER_ERROR.value()); //服務器內部錯誤response.setContentType("application/json;charset=utf-8");response.getWriter().write(objectMapper.writeValueAsString(e));}else{super.onAuthenticationFailure(request, response, e);}} } VstudyAuthenticationFailHandler

?

?

2 認證流程

?

?

3 圖形驗證碼

3.1 生成圖形驗證碼

  驗證碼圖片信息:

public class ImageCode {private BufferedImage image;private String code;private LocalDateTime expireTime;//過期時間public ImageCode(BufferedImage image, String code, int expireIn){this.image = image;this.code = code;this.expireTime = LocalDateTime.now().plusSeconds(expireIn);}public ImageCode(BufferedImage image, String code, LocalDateTime expireTime){this.image = image;this.code = code;this.expireTime = expireTime;} } ImageCode

?

?

  控制器:

@RestController public class ValidateCodeController {public static String SESSION_KEY = "SESSION_KEY_IMAGE_CODE";private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();@Autowiredprivate SecurityProperties securityProperties;@GetMapping("/image/code")public void createCode(HttpServletRequest request, HttpServletResponse response) throws IOException {ImageCode imageCode = createImageCode(new ServletWebRequest(request,response));sessionStrategy.setAttribute(new ServletWebRequest(request, response), SESSION_KEY, imageCode);ImageIO.write(imageCode.getImage(), "JPEG", response.getOutputStream());}/*** 生成ImageCode驗證碼* @param request* @return*/public ImageCode createImageCode(ServletWebRequest request){// 生成驗證碼,方法很多int width = 60;int height = 20;BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);Graphics g = image.getGraphics();Random random = new Random();g.setColor(getRandColor(200, 250));g.fillRect(0, 0, width, height);g.setFont(new Font("Times New Roman", Font.ITALIC, 20));g.setColor(getRandColor(160, 200));for (int i = 0; i < 155; i++) {int x = random.nextInt(width);int y = random.nextInt(height);int xl = random.nextInt(12);int yl = random.nextInt(12);g.drawLine(x, y, x + xl, y + yl);}String sRand = "";for (int i = 0; i < 4; i++) {String rand = String.valueOf(random.nextInt(10));sRand += rand;g.setColor(new Color(20 + random.nextInt(110), 20 + random.nextInt(110), 20 + random.nextInt(110)));g.drawString(rand, 13 * i + 6, 16);}g.dispose();return new ImageCode(image, sRand, 100);}/*** 生成隨機背景條紋** @param fc* @param bc* @return*/private Color getRandColor(int fc, int bc) {Random random = new Random();if (fc > 255) {fc = 255;}if (bc > 255) {bc = 255;}int r = fc + random.nextInt(bc - fc);int g = fc + random.nextInt(bc - fc);int b = fc + random.nextInt(bc - fc);return new Color(r, g, b);} } ValidateCodeController

?

?

3.2 驗證碼校驗

?自定義過濾器:

public class ValidateCodeFilter extends OncePerRequestFilter {/*** 驗證碼校驗失敗處理器*/private AuthenticationFailureHandler authenticationFailureHandler;/*** 系統配置信息*/private SessionStrategy sessionStrategy = new HttpSessionSessionStrategy();/*** 系統中的校驗碼處理器*/@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {// 只處理登錄請求if (StringUtils.equals("/authetication/form", request.getRequestURI())&& StringUtils.equalsIgnoreCase(request.getMethod(), "POST")) {try {logger.info("驗證碼校驗通過");} catch (ValidateCodeException e) {//驗證失敗 authenticationFailureHandler.onAuthenticationFailure(request, response, e);}}filterChain.doFilter(request, response);}protected void validate(ServletWebRequest request) throws ServletRequestBindingException {// 從session中拿到imageCodeImageCode codeInSession = (ImageCode) sessionStrategy.getAttribute(request, ValidateCodeController.SESSION_KEY);// 獲取客戶端輸入的code,當前請求參數String codeInRequest = ServletRequestUtils.getStringParameter(request.getRequest(), "imageCode");if(StringUtils.isBlank(codeInRequest)){throw new ValidateCodeException("驗證碼不能為空");}if(codeInSession==null){throw new ValidateCodeException("驗證碼不存在");}if(codeInSession.isExpired()){throw new ValidateCodeException("驗證碼已過期");}if(!StringUtils.equalsIgnoreCase(codeInSession.getCode(), codeInRequest)){throw new ValidateCodeException("驗證碼不匹配");}sessionStrategy.removeAttribute(request, ValidateCodeController.SESSION_KEY);}public AuthenticationFailureHandler getAuthenticationFailureHandler() {return authenticationFailureHandler;}public void setAuthenticationFailureHandler(AuthenticationFailureHandler authenticationFailureHandler) {this.authenticationFailureHandler = authenticationFailureHandler;} } ValidateCodeFilter

?

?

配置:

?

執行流程:

?/index.html ->redirect ->/authentication/require(控制器,判斷是.html結尾)->login.html ->ValidateCodeFilter ->exception ->?VstudyAuthenticationFailHandler ->loginType:JSON

?

login.html中,使用ajax發送登錄請求 -> 驗證碼過濾器通過 -> UsernamePasswordFilter通過 -> 返回登錄結果信息

?

3.3 驗證碼的接口

  • 為了方便修改驗證碼的參數,如寬度、高度、長度等信息,我們將通過配置文件的形式配置這些信息。還有驗證碼的URL地址。
  • 驗證碼攔截的接口可配置,比如為了限制用戶操作頻率,對用戶操作使用驗證碼進行限制。驗證碼過濾器可以攔截多個控制器請求。
  • 驗證碼的生成邏輯可以配置

三級配置:

?

?1)驗證碼參數:

  默認配置:

/*** 圖形驗證碼*/ public class ImageCodeProperties {private int width = 67;private int height = 23;private int len = 4;private int expireIn = 60; //60秒后過期 //seter getter }

?

?驗證碼信息:

/*** 驗證碼:包括圖形驗證碼、短信驗證碼*/ public class ValidateCodeProperties {private ImageCodeProperties image; }

?

?屬性讀取:

@ConfigurationProperties(prefix = "getword.security") public class SecurityProperties {// browser的屬性會匹配getword.security.browser后面的屬性private BrowserProperties browser = new BrowserProperties();// 驗證碼屬性匹配getword.security.code后面的屬性private ValidateCodeProperties code = new ValidateCodeProperties(); }

?

?

?

?

?

?

end

轉載于:https://www.cnblogs.com/zhuxiang1633/p/10311320.html

總結

以上是生活随笔為你收集整理的spring security认证的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。