对于Security认证有两种方式一种是表单方式,一种是HttpBasic认证方式。Spring security 5.x以下默认是HttpBasic认证,以上默认是表单认证。表单认证可以使用formLogin()进行配置。
formLogin默认使用UsernamePasswordAuthenticationFilter过滤器,ProviderManager认证管理,DaoAuthenticationProvider。
这里使用springboot工程进行开发。
1.新建一个登录页面
新建一个登录页面并且将登录页面放置到resources目录下的static目录中。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>登陆</title>
</head>
<style>
.form-control {
height: 25px;
}
label{
font-size: 20px;
}
label.username-calss {
font-weight: bold
}
</style>
<body>
<div style="text-align: center;">
<form id="login-form" class="form" action="/doLogin" method="post">
<h3>登录</h3>
<label for="username" class="text-into username-calss">用户名</label><br>
<input type="text" name="uname" id="username" class="form-control"><br>
<label for="password" class="text-info">密码</label><br>
<input type="password" name="passwd" id="password" class="form-control"><br>
<input type="submit" name="submit" class="btn btn-info btn-md" value="登录">
</form>
</div>
</body>
</html>
2.自定义配置
新建一个配置类WebSecurityConfig,并且继承WebSecurityConfigurerAdapter(如果WebSecurityConfigurerAdapter。
@Configuration
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserDetailsService myUserDetailsService;
/**
* formLogin() 默认使用了UsernamePasswordAuthenticationFilter
* 默认使用了DaoAuthenticationProvider认证逻辑,使用configure可以配置UserDetailsService
*
* @param http
* @throws Exception
*/
@Override
public void configure(HttpSecurity http) throws Exception {
//忽略hellopost接口
http.csrf().disable();
http.authorizeRequests()
.antMatchers("/hello", "/loginalert", "/mylogin").permitAll()
.antMatchers("/helloadmin").hasRole("admin")
.antMatchers("/hellouser").hasAuthority("query")
.anyRequest().authenticated()
.and().formLogin().loginPage("/mylogin.html")
.usernameParameter("uname").passwordParameter("passwd")
.permitAll()
.loginProcessingUrl("/doLogin")
//登录失败处理
.failureHandler((request, response, exception) -> {
String message = "login fail:" + exception.getMessage();
response.setContentType("text/html");
response.getWriter().write("<script>alert('" + message + "');window.location.href='/mylogin.html'</script>");
//登录成功处理
}).successHandler(((request, response, authentication) -> {
String message = "login success:" + authentication.getName();
response.setContentType("text/html");
response.getWriter().write("<script>alert('" + message + "');window.location.href='/index'</script>");
}));
//权限失败
http.exceptionHandling().accessDeniedHandler(((request, response, accessDeniedException) -> {
String message = "access fail:" + accessDeniedException.getMessage();
response.setContentType("text/html");
response.getWriter().write("<script>alert('" + message + "');window.location.href='/index'</script>");
}));
}
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception {
return super.authenticationManagerBean();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(myUserDetailsService);
}
}
配置类
@Configuration
public class MyConfig {
@Bean
PasswordEncoder bcryptPasswordEncoder() {
return new BCryptPasswordEncoder();
}
@Bean
UserDetailsService myUserDetailsService() {
return new MyUserDetailsService();
}
}
MyUserDetailsService:
public class MyUserDetailsService implements UserDetailsService {
Map<String, String> user = new HashMap();
Map<String, List<String>> userRole = new HashMap<>();
{
user.put("lixin", "123456");
user.put("zs", "111111");
//hasRole 的处理逻辑和 hasAuthority 似乎是一样的,只是hasRole 这
// 里会自动给传入的字符串前缀(默认是ROLE_ ),
// 使用 hasAuthority 更具有一致性,不用考虑要不要加 ROLE_ 前缀,
// 在UserDetailsService类的loadUserByUsername中查询权限,也不需要手动增加。
// 在SecurityExpressionRoot 类中hasAuthority 和 hasRole
// 最终都是调用了 hasAnyAuthorityName 方法。
userRole.put("lixin", Arrays.asList("ROLE_admin"));
userRole.put("zs", Arrays.asList("query"));
}
@Autowired
PasswordEncoder passwordEncoder;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if (!user.containsKey(username)) {
throw new UsernameNotFoundException("username is not exists");
}
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
if (userRole.containsKey(username)) {
authorities = userRole.get(username).stream().map(row -> new SimpleGrantedAuthority(row))
.collect(Collectors.toList());
}
return new User(username, passwordEncoder.encode(user.get(username)), authorities);
}
}
3.如果WebSecurityConfigurerAdapter过期,可以使用SecurityFilterChain进行配置。
@Bean
SecurityFilterChain managementSecurityFilterChain(HttpSecurity http) throws Exception {
return http.authorizeRequests()
.antMatchers("/hello2").permitAll()
.anyRequest().authenticated()
.and().formLogin()
.and()
.build();
}
文章介绍了在Springsecurity框架中,如何配置表单认证,包括创建登录页面、自定义配置类WebSecurityConfig,以及设置登录失败和成功的处理方式。此外,还提到了WebSecurityConfigurerAdapter的使用,并给出了权限失败的处理方法。
&spm=1001.2101.3001.5002&articleId=131274703&d=1&t=3&u=52230cb472024fa28a4790ca18c8173c)
805

被折叠的 条评论
为什么被折叠?



