Spring Security的簡單使用
推薦 Java 常見面試題
簡介
- SSM 整合 Security 是比較麻煩的,雖然Security的功能比 Shiro 強大,相反卻沒有Shiro的使用量多
- SpringBoot出現后簡化了Spring系列的配置文件,因此SpringSecurity的使用逐漸增加
一、創建項目
在 SpringBoot 中直接引入 Spring Security 依賴即可
創建項目的啟動類
創建 SecurityController 類
- 啟動后訪問
localhost:8080/hello
- 會自動跳到
localhost:8080/login
- 需要登錄后才能訪問
/hello
二、用戶名配置
- 默認情況下用戶名是
user
,而密碼會在項目啟動時控制台
打印出一串隨機字符串
,這就是密碼.每次啟動項目,密碼都不一樣
- 對登錄的用戶名/密碼進行配置,有三種不同的方式
- 在
application
配置文件中聲明- 在
java
代碼配置在內存里- 通過獲取
數據庫
第一種方式
application.yml
文件中
第二種方式 創建一個
SecurityConfig
配置類,繼承WebSecurityConfigurerAdapter
第三種方法沒有進行演示,就是在數據庫中取出
username
和password
配置到內存中
三、忽略攔截
在配置類中重寫
configure(WebSecurity web)
方法,然后直接訪問即可
pom.xml文件
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<!--Web項目 需引入web依賴-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
啟動類文件
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @author https://www.cnblogs.com/beixuan/
*/
@SpringBootApplication
public class SecurityApplication {
public static void main(String[] args) {
SpringApplication.run(SecurityApplication.class, args);
}
}
SecurityController 文件
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author https://www.cnblogs.com/beixuan/
*/
@RestController
public class SecurityController {
/**
* 不用登錄就可訪問
* @return
*/
@RequestMapping("/hi")
public String sayHi(){
return "Hi bro!";
}
@RequestMapping("/hello")
public String sayHello(){
return "Hello bro!";
}
}
application.yml 配置文件
spring:
security:
user:
name: beixuan
password: beixuan
SecurityConfig Java配置文件
此方法配置用戶與配置
yml
文件效果一致
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.crypto.password.PasswordEncoder;
/**
* @author https://www.cnblogs.com/beixuan/
*/
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
//Spring Security5之后 官方需要密碼強制加密,如不想加密可創建一個過期的 PasswordEncoder 的實例 NoOpPasswordEncoder,但不安全
BCryptPasswordEncoder bCryptPasswordEncoder = new BCryptPasswordEncoder();
String password = bCryptPasswordEncoder.encode("beixuan");
//添加一個用戶[beixuan] 角色為[admin] 密碼是[beixuan加密后的密鑰]
auth.inMemoryAuthentication()
.withUser("beixuan")
.roles("admin")
.password(password);
}
@Bean
PasswordEncoder passwordEncoder(){
return new BCryptPasswordEncoder();
}
}
- 具體的登錄配置 下面代碼借鑒於 江南一點雨 隨筆的代碼,有興趣可以看看
VerifyCodeFilter
一次性驗證碼,可以查看資料了解其使用方法,這里不再敘述
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
VerifyCodeFilter verifyCodeFilter;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.addFilterBefore(verifyCodeFilter, UsernamePasswordAuthenticationFilter.class);
http
.authorizeRequests()//開啟登錄配置
.antMatchers("/hello").hasRole("admin")//表示訪問 /hello 這個接口,需要具備 admin 這個角色
.anyRequest().authenticated()//表示剩余的其他接口,登錄之后就能訪問
.and()
.formLogin()
//定義登錄頁面,未登錄時,訪問一個需要登錄之后才能訪問的接口,會自動跳轉到該頁面
.loginPage("/login_p")
//登錄處理接口
.loginProcessingUrl("/doLogin")
//定義登錄時,用戶名的 key,默認為 username
.usernameParameter("uname")
//定義登錄時,用戶密碼的 key,默認為 password
.passwordParameter("passwd")
//登錄成功的處理器
.successHandler(new AuthenticationSuccessHandler() {
@Override
public void onAuthenticationSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write("success");
out.flush();
}
})
.failureHandler(new AuthenticationFailureHandler() {
@Override
public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp, AuthenticationException exception) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write("fail");
out.flush();
}
})
.permitAll()//和表單登錄相關的接口統統都直接通過
.and()
.logout()
.logoutUrl("/logout")
.logoutSuccessHandler(new LogoutSuccessHandler() {
@Override
public void onLogoutSuccess(HttpServletRequest req, HttpServletResponse resp, Authentication authentication) throws IOException, ServletException {
resp.setContentType("application/json;charset=utf-8");
PrintWriter out = resp.getWriter();
out.write("logout success");
out.flush();
}
})
.permitAll()
.and()
.httpBasic()
.and()
.csrf().disable();
}
忽略攔截分兩步
增加訪問路徑
/hi
/**
* 不用登錄就可訪問
* @return
*/
@RequestMapping("/hi")
public String sayHi(){
return "Hi bro!";
}
增加配置代碼
@Override
public void configure(WebSecurity web) throws Exception {
web.ignoring().antMatchers("/hi");
}
即可不用登錄訪問
/hi
路徑
END
本文就先說到這里,有問題歡迎留言討論