Spring Security 使用者密碼配置
配置檔案
Spring Boot中整合Spring Security隻需添加一個依賴即可,非常友善,啟動項目時:控制台會輸出一個密碼,在浏覽器通路時會彈出一個登入框,預設使用者為user,而密碼就是控制台輸出的那段字元串。
那這樣就會有一個問題,每次通路都需要複制控制台的密碼,當然,這個是可以配置的,可以在配置檔案當中進行如下配置。
spring.security.user.name=user
spring.security.user.password=youyuan
此時,通路浏覽器登入即可。
記憶體配置
當然也可以基于記憶體進行配置,建立一個類繼承自WebSecurityConfigurerAdapter然後實作其configuration方法即可。
@Configuration
public class MultiHttpSecurityConfig extend WebSecurityConfigurerAdapter{
//對密碼不進行加密處理
@Bean
PasswordEncoder passwordEncoder(){
return NoOpPasswordEncoder.getInstance();
}
@Autowired
/*使用者認證*/
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.inMemoryAuthentication()
.withUser("youyuan").password("1011").roles("admin")
.and()
.withUser("zs").password("1011").roles("user");
}
}
注意:基于記憶體的使用者配置在配置角色時不需要添加"ROLE_ "字首
資料庫配置
當然在實際開發情況下,使用者與密碼還是要從資料庫當中加載,基于資料庫進行認證。
首先我們準備三個表,分别為使用者,角色,還有使用者角色表。使用者角色表關聯每個使用者所對應的角色。

在配置基本的資料庫資訊:
spring.datasource.type=com.alibaba.druid.pool.DruidDataSource
spring.datasource.password=root
spring.datasource.username=root
spring.datasource.url=jdbc:mysql://localhost:3306/testcharacterEncoding=utf-8&serverTimezone=UTC
然後在建立對應的實體類:
@Data
public class User implements UserDetails {
private Integer id;
private String username;
private String password;
private Boolean enabled;
private Boolean locked;
private List<Role> roles;
@Override
/*傳回使用者所有角色*/
public Collection<? extends GrantedAuthority> getAuthorities() {
List<SimpleGrantedAuthority> authorities = new ArrayList<>();
for (Role role : this.roles) {
authorities.add(new SimpleGrantedAuthority("ROLE_"+role.getName()));
}
return authorities;
}
@Override
/*賬戶是否沒有過期*/
public boolean isAccountNonExpired() {
return true;
}
@Override
/*賬戶是否未鎖定*/
public boolean isAccountNonLocked() {
return !locked;
}
@Override
/*密碼是否未過期*/
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return enabled;
}
@Override
public String getUsername() {
return username;
}
@Override
public String getPassword() {
return password;
}
}
在UserService類中實作UserDetailsService接口
@Service
public class UserService implements UserDetailsService {
@Autowired
UserMapper userMapper;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
User user = userMapper.loadUserByUsername(username);
if (user == null) {
throw new UsernameNotFoundException("使用者不存在!");
}
/**
*查詢出相應的角色
*添加角色到user中**/
user.setRoles(userMapper.getUserRolesById(user.getId()));
return user;
}
}
最後在Spring Security進行配置:
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
UserService userService;
@Override
/**
*使用者認證
**/
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(userService);
}
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
/**
**表單配置詳解
**/
@Override
protected void configure(HttpSecurity http) throws Exception {
http.authorizeRequests()//開啟登入配置
.anyRequest().authenticated() //表示通路接口,需要進行認證
.and()
.formLogin()
.loginProcessingUrl("/doLogin")
.loginPage("/login") //預設的登入頁面
.usernameParameter("user")//定義登入時,使用者名的 key,預設為 username
.passwordParameter("pwd") //定義登入時,使用者密碼的 key,預設為 password
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest request,
HttpServletResponse response, Authentication authentication) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
Map<String,Object> map = new HashMap<>();
map.put("status",200);
map.put("msg",authentication.getPrincipal());
//浏覽器傳回json資料
out.write(new ObjectMapper().writeValueAsString(map));
out.flush();
out.close();
}
})
.failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest request,
HttpServletResponse response, AuthenticationException e) throws IOException, ServletException {
response.setContentType("application/json;charset=utf-8");
PrintWriter out = response.getWriter();
Map<String,Object> map = new HashMap<>();
map.put("status",401);
if (e instanceof LockedException){
map.put("msg","賬戶被鎖定,登入失敗");
}else if (e instanceof BadCredentialsException){
map.put("msg","使用者名或密碼輸入錯誤,登入失敗");
}else if (e instanceof DisabledException){
map.put("msg","賬戶被禁用,登入失敗");
}else if(e instanceof AccountExpiredException){
map.put("msg","賬戶過期,登入失敗");
}else if (e instanceof CredentialsExpiredException){
map.put("msg","密碼過期,登入失敗");
}else {
map.put("msg","登入失敗");
}
//浏覽器傳回json資料
out.write(new ObjectMapper().writeValueAsString(map));
out.flush();
out.close();
}
})
.permitAll() //和表單登入相關的接口統統都直接通過
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
Map<String,Object> map = new HashMap<>();
map.put("status",200);
map.put("msg","登出登入成功");
//浏覽器傳回json資料
out.write(new ObjectMapper().writeValueAsString(map));
out.flush();
out.close();
}
})
.permitAll()
.and()
.csrf().disable();
}
}