Spring Security是一個可以爲基於Spring的企業應用系統提供聲明式的安全訪問控制解決方案的安全框架。它提供了一組能夠在Spring應用上下文中配置的Bean,充分利用了Spring IoC,DI(控制反轉Inversion of Control ,DI:Dependency Injection 依賴注入)和AOP(面向切面編程)功能,爲應用系統提供聲明式的安全訪問控制功能,減小了爲企業系統安全控制編寫大量重複代碼的工做。html
https://springcloud.cc/spring-security-zhcn.html 中文版參考手冊spring
UsernamePasswordAuthenticationFilter:用戶認證數據庫
ExceptionTranslation:異常處理編程
FilterSecurityInterceptor:最終確認是否能登陸的攔截器json
備註:在沒有驗證的狀況下,登陸後會到默認的驗證頁面,默認會攔截全部頁面,待驗證成功後會轉到相應的頁面安全
3.依賴app
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-security</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-test</artifactId> <scope>test</scope> </dependency>
4.Api簡要說明框架
authorizeRequests():請求受權dom
formLogin():表單登陸(表單登陸含兩部分一個是認證一個是受權)ide
anyRequest():任何請求
authenticated():身份認證
httpBasic():httpBasic認證方式
loginPage():指定登陸時的認證頁面,這裏有一個坑死循環須要注意。
antMatchers():匹配
permitAll():不須要身份認證
5.使用數據庫驗證登陸方式
@Configuration @ComponentScan("springsecurity.demo") @MapperScan("springsecurity.demo.Mapper") public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin()//表單登陸 .and() .authorizeRequests()//權限認證 .anyRequest()//任何請求 .authenticated()//須要認證 ; } }
@Component public class MyUserDetailsService implements UserDetailsService { @Autowired UserMapper userMapper; @Autowired PasswordEncoder passwordEncoder; @Override public UserDetails loadUserByUsername(String username) { //查詢表 springsecurity.demo.domain.User userByName = userMapper.getUserByName(username); //加密 String encode = passwordEncoder.encode(userByName.getPassword().toString());//應該是在放入數據庫的時候加密,這裏直接直接取出 //將查詢的結果放入user中, // AuthorityUtils.commaSeparatedStringToAuthorityList("admin")表示角色admin(擁有的權限) return new User(username,encode , AuthorityUtils.commaSeparatedStringToAuthorityList("admin"));//須要採用加密方式否者出現{id}爲null } }
@Configuration
public class SecurityBeanConfig {
@Bean
@ConfigurationProperties(prefix = "spring.datasource")
public DataSource getdaDataSource(){
return new DruidDataSource();
}
@Bean
public PasswordEncoder getPasswordEncoder(){
return new BCryptPasswordEncoder();//springsecurity 內置的加密器,建議使用
}
}
@RestController public class UserController { @GetMapping("/hello") public String testLogin(){ return "helloworld security"; } }
自定義加密方式
須要實現PasswordEncoder
重寫方法
encode:對密碼進行加密
matches(CharSequence var1, String var2):var1原密碼,var2傳過來的密碼
User(String username, String password, boolean enabled, boolean accountNonExpired, boolean credentialsNonExpired, boolean accountNonLocked, Collection<? extends GrantedAuthority> authorities)
enabled:是否可用
accountNonExpired:帳戶是否過時
credentialsNonExpired:密碼是否過時
accountNonLocked:是否被凍結
6.自定義登陸頁面
6.1使用默認的自定義方式配置
@Configuration @ComponentScan("springsecurity.demo") @MapperScan("springsecurity.demo.Mapper") public class SecurityConfig extends WebSecurityConfigurerAdapter { @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() .loginPage("/logintest.html") //登陸頁面定義 .loginProcessingUrl("/authentication/logintest")//默認處理的是login post .and() .authorizeRequests() .antMatchers("/logintest.html") .permitAll() .anyRequest() .authenticated() .and() .csrf().disable()//跨站域請求僞造關閉,注意不關閉在Chrome中沒反應 ; } }
6.2使用自定義配置登陸頁面
@Configuration
@ComponentScan("springsecurity.demo")
@MapperScan("springsecurity.demo.Mapper")
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Autowired
MySecurityProperties mySecurityProperties;
@Override
protected void configure(HttpSecurity http) throws Exception {
http.formLogin()
.loginPage("/logintest")
.loginProcessingUrl("/authentication/logintest")
.and()
.authorizeRequests()
.antMatchers("/logintest",mySecurityProperties.getLogin())
.permitAll()
.anyRequest()
.authenticated()
.and()
.csrf().disable()
;
}
}
@RestController public class UserController { HttpSessionRequestCache cache= new HttpSessionRequestCache(); DefaultRedirectStrategy defaultRedirectStrategy = new DefaultRedirectStrategy();//重定向頁面 @Autowired MySecurityProperties securityProperties; @GetMapping("/logintest") @ResponseStatus(HttpStatus.UNAUTHORIZED) public Message testAuthentication(HttpServletRequest request, HttpServletResponse response) throws IOException { SavedRequest savedRequest = cache.getRequest(request, response); if(savedRequest!=null){ String redirectUrl = savedRequest.getRedirectUrl();//獲取請求地址 if(StringUtils.endsWithIgnoreCase(redirectUrl, ".html")){ defaultRedirectStrategy.sendRedirect(request, response, securityProperties.getLogin()); } } return new Message("請先登陸"); } }
@AllArgsConstructor @NoArgsConstructor @Data @Accessors(chain = true) public class Message implements Serializable { private Object mesaage; }
<body>
<h2 style="color: red">簡單的登陸頁面login</h2>
<form action="/authentication/logintest" method="post">
<table>
<tr>
<td>帳號:</td>
<td ><input type="text" name="username"/></td>
</tr>
<tr>
<td>密碼:</td>
<td> <input type="password" name="password"/></td>
</tr>
<tr>
<td colspan="2" style="text-align: right"><input type="submit" value="提交" /></td>
</tr>
</table>
</form>
</body>
</html>
@ConfigurationProperties("spring.security") @AllArgsConstructor @NoArgsConstructor @Data @Accessors(chain = true) @Component public class MySecurityProperties { private String login="/logintest.html"; }
7.自定義成功登錄的返回值
@Configuration @ComponentScan("springsecurity.demo") @MapperScan("springsecurity.demo.Mapper") public class SecurityConfig extends WebSecurityConfigurerAdapter { @Autowired MySecurityProperties mySecurityProperties; @Autowired MyUserDetails myUserDetails; @Override protected void configure(HttpSecurity http) throws Exception { http.formLogin() .loginPage("/logintest") .loginProcessingUrl("/authentication/logintest") .successHandler(myUserDetails) .and() .authorizeRequests() .antMatchers("/logintest",mySecurityProperties.getLogin()) .permitAll() .anyRequest() .authenticated() .and() .csrf().disable() ; } }
@Component public class MyUserDetails implements AuthenticationSuccessHandler { @Override public void onAuthenticationSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication) throws IOException, ServletException { response.setContentType("application/json;charset=UTF-8"); response.getWriter().write(new ObjectMapper().writeValueAsString(authentication)); } }
失敗相似
實現AuthenticationFailureHandler實現onAuthenticationFailure方法
.failureHandler(AuthenticationFailureHandler xxx)
8.圖片驗證