下面是Spring Security实现用户名密码登录的详细攻略:
实现步骤
1. 添加Spring Security的Maven依赖
在项目的pom.xml文件中添加以下Maven依赖。
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
2. 配置Spring Security
在Spring Boot项目中,我们可以通过在application.properties或者application.yml配置文件中进行Spring Security的配置。
以下是一个示例的application.properties文件的配置:
# HTTP Basic 认证开关
spring.security.basic.enabled=true
# 配置用户名和密码
spring.security.user.name=admin
spring.security.user.password=admin123
以下是一个示例的application.yml文件的配置:
# HTTP Basic 认证开关
spring:
security:
basic:
enabled: true
# 配置用户名和密码
spring:
security:
user:
name: admin
password: admin123
3. 添加验证页面
创建一个HTML页面(例如:login.html),添加用户名和密码输入框,并使用POST方法提交数据到/login接口。
以下是一个示例的login.html页面:
<!DOCTYPE html>
<html>
<head>
<title>Login Page</title>
</head>
<body>
<h1>Login Page</h1>
<form method="post" action="/login">
<label for="username">Username:</label>
<input type="text" id="username" name="username" /><br /><br />
<label for="password">Password:</label>
<input type="password" id="password" name="password" /><br /><br />
<input type="submit" value="Login" />
</form>
</body>
</html>
4. 自定义认证配置
创建一个类实现org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter接口,并重写configure(HttpSecurity http)方法。
以下是一个示例的WebSecurityConfigurer类的配置:
@Configuration
@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/admin").hasAuthority("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/home")
.failureUrl("/login/error")
.permitAll()
.and()
.logout()
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
}
5. 创建自定义用户类和密码加密器
创建一个实现org.springframework.security.core.userdetails.UserDetails接口的CustomUser类,表示我们自定义的用户类型,同时创建一个实现org.springframework.security.crypto.password.PasswordEncoder接口的PasswordEncoder类,用于对用户密码进行加密处理。
以下是一个示例的CustomUser类和PasswordEncoder类的代码:
public class CustomUser implements UserDetails {
private String username;
private String password;
private List<GrantedAuthority> authorities;
// 省略getter和setter,以及实现的UserDetails接口方法
public CustomUser(String username, String password, String... roles) {
this.username = username;
this.password = password;
List<GrantedAuthority> authorities = new ArrayList<>();
for (String role : roles) {
authorities.add(new SimpleGrantedAuthority(role));
}
this.authorities = authorities;
}
}
public class PasswordEncoder implements org.springframework.security.crypto.password.PasswordEncoder {
@Override
public String encode(CharSequence charSequence) {
return DigestUtils.sha256Hex(charSequence.toString());
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(encode(charSequence));
}
}
6. 创建自定义用户服务类
创建一个实现org.springframework.security.core.userdetails.UserDetailsService接口的CustomUserDetailsService类,用于根据用户名查询用户信息。
以下是一个示例的CustomUserDetailsService类的代码:
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
// TODO: 从数据库中查询用户信息,并返回CustomUser对象
CustomUser user = new CustomUser("admin", new PasswordEncoder().encode("admin123"), "ADMIN");
return user;
}
}
示例
示例一
配置文件
以下是示例一的application.yml文件的配置:
spring:
security:
basic:
enabled: true
自定义认证配置
以下是示例一的WebSecurityConfigurer类的配置:
@Configuration
@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests().anyRequest().authenticated().and().httpBasic();
}
}
控制器
以下是示例一的控制器类的代码:
@RestController
public class TestController {
@GetMapping("/")
public String index() {
return "Hello World";
}
@GetMapping("/admin")
public String admin() {
return "Hello Admin";
}
}
示例说明
在示例一中,我们启用了HTTP Basic 认证,使用浏览器访问应用时,会弹出用户名和密码输入框,输入正确的用户名和密码后才能访问应用中的资源。
访问根路径(/)时,会提示输入用户名和密码。输入正确的用户名(admin)和密码(admin123)后,会看到页面上显示“Hello World”。
访问/admin时,同样需要输入用户名和密码,成功认证后,显示“Hello Admin”。
示例二
控制器
以下是示例二的控制器类的代码:
@RestController
public class TestController {
@GetMapping("/")
public String index() {
return "Hello World";
}
@GetMapping("/login")
public ModelAndView login(ModelAndView modelAndView) {
modelAndView.setViewName("login");
return modelAndView;
}
@GetMapping("/home")
public String home() {
return "Hello Home";
}
@GetMapping("/admin")
public String admin() {
return "Hello Admin";
}
@GetMapping("/login/error")
public ModelAndView loginError(ModelAndView modelAndView) {
modelAndView.addObject("error", true);
modelAndView.setViewName("login");
return modelAndView;
}
}
配置文件
以下是示例二的application.yml文件的配置:
spring:
security:
basic:
enabled: false
thymeleaf:
cache: false
自定义认证配置
以下是示例二的WebSecurityConfigurer类的配置:
@Configuration
@EnableWebSecurity
public class WebSecurityConfigurer extends WebSecurityConfigurerAdapter {
@Autowired
private CustomUserDetailsService userDetailsService;
@Autowired
private PasswordEncoder passwordEncoder;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()
.antMatchers("/login").permitAll()
.antMatchers("/admin").hasAuthority("ADMIN")
.anyRequest().authenticated()
.and()
.formLogin()
.loginPage("/login")
.defaultSuccessUrl("/home")
.failureUrl("/login/error")
.permitAll()
.and()
.logout()
.permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userDetailsService).passwordEncoder(passwordEncoder);
}
}
自定义用户类和密码加密器
以下是示例二的CustomUser类和PasswordEncoder类的代码:
public class CustomUser implements UserDetails {
private String username;
private String password;
private List<GrantedAuthority> authorities;
// 省略getter和setter,以及实现的UserDetails接口方法
public CustomUser(String username, String password, String... roles) {
this.username = username;
this.password = password;
List<GrantedAuthority> authorities = new ArrayList<>();
for (String role : roles) {
authorities.add(new SimpleGrantedAuthority(role));
}
this.authorities = authorities;
}
}
public class PasswordEncoder implements org.springframework.security.crypto.password.PasswordEncoder {
@Override
public String encode(CharSequence charSequence) {
return DigestUtils.sha256Hex(charSequence.toString());
}
@Override
public boolean matches(CharSequence charSequence, String s) {
return s.equals(encode(charSequence));
}
}
自定义用户服务类
以下是示例二的CustomUserDetailsService类的代码:
@Service
public class CustomUserDetailsService implements UserDetailsService {
@Override
public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
// TODO: 从数据库中查询用户信息,并返回CustomUser对象
CustomUser user = new CustomUser("admin", new PasswordEncoder().encode("admin123"), "ADMIN");
return user;
}
}
静态资源和模板文件
创建一个login.html的模板文件,用于显示登录页面。
以下是一个示例的login.html文件的内容:
<!DOCTYPE html>
<html>
<head>
<title>Login Page</title>
</head>
<body>
<h1>Login Page</h1>
<div th:if="${param.error}">
Invalid username or password.
</div>
<form method="post" action="/login">
<label for="username">Username:</label>
<input type="text" id="username" name="username" /><br /><br />
<label for="password">Password:</label>
<input type="password" id="password" name="password" /><br /><br />
<input type="submit" value="Login" />
</form>
</body>
</html>
创建一个static文件夹,并在其中创建一个图片文件(例如:logo.png)。
示例说明
在示例二中,我们关闭了HTTP Basic 认证,启用了表单登录认证。访问根路径(/)时,会自动跳转到/login接口,展示登录页面(login.html)。
输入正确的用户名(admin)和密码(admin123)后,会自动跳转到/home页面,并显示“Hello Home”。
访问/admin时,因为没有该用户的角色授权,会跳转到/error页面。
如果账号或密码不正确,会跳转回登录页面,并提示“Invalid username or password.”。
示例二还演示了如何设置静态资源文件,以及如何解析模板文件。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Spring Security实现用户名密码登录详解 - Python技术站