其他分享
首页 > 其他分享> > spring secuity登录不跳转问题解决及自定义密码分析

spring secuity登录不跳转问题解决及自定义密码分析

作者:互联网

之前用spring security写一个登录demo的时候,一直遇到一个问题,在登录页面登录之后,一直不进行跳转,一直在登录界面,然后找了好久,才找到原因。
先来讲我遇到这个问题的解决办法。
先进行配置html页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Title</title>
</head>
<body>
<form action="/login" method="post">
    <input name="username" type="text"/>用户名
    <br>
    <input name="password"  type="text" />密码
    <br>
    <!--在这里遇到了一个问题,因为登录的时候我最开始传的是${_csrf.getHeaderName()} ,
    然后我看了CsrfFilter类的doFilterInternal方法后才发现${_csrf.parameterName}
    才会有后面的验证,然后我把这里改了之后就成功了
    但是我看源码里面其实也有获取getHeadName()这个方法,没理解到这里-->
    <input th:name="${_csrf.parameterName}" th:value="${_csrf.token}">
    <input type="submit"></input>
</form>
</body>
</html>

在csrfFilter里,每次登录都会有一个验证

protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain)
			throws ServletException, IOException {
		request.setAttribute(HttpServletResponse.class.getName(), response);
		CsrfToken csrfToken = this.tokenRepository.loadToken(request);
		boolean missingToken = (csrfToken == null);
		if (missingToken) {
			csrfToken = this.tokenRepository.generateToken(request);
			this.tokenRepository.saveToken(csrfToken, request, response);
		}
		request.setAttribute(CsrfToken.class.getName(), csrfToken);
		request.setAttribute(csrfToken.getParameterName(), csrfToken);
		if (!this.requireCsrfProtectionMatcher.matches(request)) {
			if (this.logger.isTraceEnabled()) {
				this.logger.trace("Did not protect against CSRF since request did not match "
						+ this.requireCsrfProtectionMatcher);
			}
			filterChain.doFilter(request, response);
			return;
		}
		String actualToken = request.getHeader(csrfToken.getHeaderName());
		if (actualToken == null) {
			actualToken = request.getParameter(csrfToken.getParameterName());
		}
		if (!csrfToken.getToken().equals(actualToken)) {
			this.logger.debug(
					LogMessage.of(() -> "Invalid CSRF token found for " + UrlUtils.buildFullRequestUrl(request)));
			AccessDeniedException exception = (!missingToken) ? new InvalidCsrfTokenException(csrfToken, actualToken)
					: new MissingCsrfTokenException(actualToken);
			this.accessDeniedHandler.handle(request, response, exception);
			return;
		}
		filterChain.doFilter(request, response);
	}

在String actualToken = request.getHeader(csrfToken.getHeaderName());
if (actualToken == null) {
actualToken = request.getParameter(csrfToken.getParameterName());
}
这里我不是很清楚为什么取不到request.getHeader(csrfToken.getHeaderName());
了解的大佬麻烦告诉下

然后后面就是

@Configuration //之前写过配置类的作用 这里就是相当于定义为一个Spring容器
@EnableWebSecurity //简单理解为默认开启crsf防护
public class MyConfig extends WebSecurityConfigurerAdapter {
    Logger log = LoggerFactory.getLogger(MyConfig.class);
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        System.out.println(new BCryptPasswordEncoder().encode("111"));
        log.info("{}值",new BCryptPasswordEncoder().encode("111"));
        http.
        authorizeRequests() .antMatchers("/hi","/success","/login.html").permitAll().
        anyRequest().authenticated().
        and().
        //登录页面
        formLogin().loginPage("views/login.html").permitAll().
        //这里的登录确认页面,这里需要和html里面form表单里面的action一样
        loginProcessingUrl("/login").permitAll().
             //登录成功后固定跳转的页面
                defaultSuccessUrl("/ok",true).permitAll().
                //这里是失败后,可以获取失败的原因的地方
                failureHandler(new AuthenticationFailureHandler() {
                    @Override
                    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                        e.printStackTrace();
                    }
                }).permitAll().
        and().
        csrf()  .csrfTokenRepository(new HttpSessionCsrfTokenRepository());
        /*如果实在解决不了登录那个问题可以用
        csrf().disable();
        或者
        csrf().ignoringAntMatchers("/login") 
        都可以登录成功
*/
    }

	//这里主要是对密码进行加密
   @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        //auth.userDetailsService().passwordEncoder();
        /*我在这里也遇到一个问题,如果这里只写了user和password的话是会出错
       然后我看了inMemoryAuthentication的源码之后,发现有6个还是7个必输项
       但是有一个必输项必须给值就是roles,其他的几个必输项是一个填充项
       所以可以不给初始值,启动不会报错,感觉和官方的解释有点矛盾
       */
        auth.inMemoryAuthentication().withUser("111").password(new BCryptPasswordEncoder().encode("111")).roles("admin").authorities("1");
    }
	/*
	加密这里大致说一下 现在一般常见的就是md5,md5虽然很快但是很容易被破解
	比如说字典啊,彩虹表之类的。所以一般情况下就需要加salt(加盐)。
	加盐的大致理解可以为在原密码上加上固定盐或者随机盐
	加固定盐的坏处显而易见,也会很容易被破解。
	那么加随机盐的话,那么随机盐是怎么生成的,还有这个随机盐是保存在哪里,
	随机盐的生成其实可以取一些逻辑,比如你的账户中,你的用户名中,然后把
	生成的随机盐放放在自己的密码中,比如放在密码的最后面。
	如果用户登录的话,从数据库取到有随机盐的密文密码,然后把密文密码进行分解
	,把盐那到后在和输入的密码进行组合后进行加密后在对比
	*/
    @Bean
    public BCryptPasswordEncoder passwordEncoder(){
        return new BCryptPasswordEncoder();
    }
}

如果本篇内容有问题,请第一时间联系我,我会第一时间修改。
谢谢大家。

标签:secuity,登录,自定义,actualToken,request,跳转,csrfToken,new,response
来源: https://blog.csdn.net/qq_38091343/article/details/110915558