1.spring security简单的demo-适合萌新
文章目錄
- 1.spring security入門
-
- 1.創建項目,引入依賴
- 2.security的其他配置方式
-
- 2.2基于內存
- 2.3HttpSecurity(入門配置此文件)
- 2.4多個HttpSecurity的配置(復雜業務場景下)---security
- 2.5配置方法安全
- 2.6基于數據庫的認證(基礎入門)-----sercuty-db/sercurity-dy
-
- 1.定義實體類user(繼承UserDetails)和role
- 2.配置SecurityConfig
- 3.動態權限配置的Security寫法
-
- 1. 1.先定義MyFilter實現FilterInvocationSecurityMetadataSource
- 3.1SecurityConfig的寫法
- 2.7spring security整合oauth2---oauth2
-
- 2.7.1配置資源服務器 ResourceServerConfig
- 2.7.2授權服務器 AuthorizationServerConfig
- 2.7.3security配置文件
- 2.7.4 MyFilter
- 2.7.5 MyAccessDecisionManager
- 2.7.6 postman測試 -請求token
- 2.8spring security支持json登錄---security-dy/security-db/oauth2
-
- 2.8.1重寫UsernamePasswordAuthenticationFilter方法
- 2.8.2注入重寫的方法
- 2.8.3配置登錄成功后的轉跳和失敗后轉跳
- 2.9spring security整合jwt --jwt-demo
-
- 2.9.1 JwtLoginFilter _登錄的時候給用戶token_
- 2.9.2. _訪問系統的時候效驗token_
- 2.9.3增加security的相關配置 configure_(_HttpSecurity http_) _
- 2.10 oauth2 整合jwt+swagger ---swcurity-swagger/ 松哥例子swagger-jwt
-
- 2.10.1.AccessTokenConfig
- 2.10.2AuthorizationServer
- 2.10.3ResourceServerConfig
- 2.10.4 GlobalCorsConfiguration ---支持跨域
- 2.11configure其他配置
1.spring security入門
decurity-demo.sql 數據庫驗證的文件
密碼是123或者123456/ 可以使用 new BCryptPasswordEncoder_().encode(“123”)_;加密出來
模板項目地址https://gitee.com/find_me/java-findme
1.創建項目,引入依賴
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>
</dependency>
引入依賴后,項目中所有的接口就會被保護起來,項目默認用戶名為user,密碼為啟動后隨即生成的,在控制臺打印的密碼
2.security的其他配置方式
spring:security:user: name: find mepassword: 123456roles: admin
2.2基于內存
當然,開發者也可以自定義類繼承自WebSecurityConfigurerAdapter ,進而實現對 Spring Security
更多的自定義配置,例如基于內存的認證,配置方式如下:
@Configuration public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter { // 密碼不加密的配置 ,過時的方法@Bean //PasswordEncoder passwordEncoder () { //return NoOpPasswordEncoder. getlnstance () ; // }// 密碼需要加密@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}//基于內存的配置@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("javaboy").password("$2a$10$KlbLLUVVyvP0/vuhlabv0upg/ALdCrVEhUJOJDEND5ZtZJ.nGfVCm").roles("admin").and().withUser("findme").password("$2a$10$KlbLLUVVyvP0/vuhlabv0upg/ALdCrVEhUJOJDEND5ZtZJ.nGfVCm").roles("user");}
代碼解釋:
·自定義 MyWebSecurityConfig 繼承自 WebSecurityConfigurerAdapter ,并重寫configure(AuthenticationManagerBuilder auth)方法,在該方法中配直兩個用戶,一個用戶名是
admin,密碼123 ,具備兩個角色 ADMIN USER 另一個用戶名是 findme,密碼是 123 ,具備一個角色USER
Spring Security 本是 0.6 Spring Security 中引入了 多種密碼加密方式,開發者必須指定其中一種, NoOpPasswordEncoder ,即不對密碼進行加密。
注意:基于配置和內存的方式在配置角色的時候不需要添加"ROLE_".基于數據庫的需要
2.3HttpSecurity(入門配置此文件)
根據實際情況進行角色配置
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Resourceprivate ObjectMapper objectMapper;@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}// 配置登錄的賬號@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("javaboy").password("$2a$10$KlbLLUVVyvP0/vuhlabv0upg/ALdCrVEhUJOJDEND5ZtZJ.nGfVCm").roles("admin").and().withUser("findme").password("$2a$10$KlbLLUVVyvP0/vuhlabv0upg/ALdCrVEhUJOJDEND5ZtZJ.nGfVCm").roles("user");}//基本的httpSecurity配置// 1.請求路徑角色// 2.配置表單登錄// 3.配置登錄成功,失敗或者登出的處理方式// authentication里面存放登錄成功后的信息// {// "password": null, 密碼// "username": "javaboy",// "authorities": [ 具備的角色// {// "authority": "ROLE_admin" // }// ],// "accountNonExpired": true, 賬戶沒有過期,// "accountNonLocked": true, 賬戶沒有鎖定// "credentialsNonExpired": true, 密碼沒有過期// "enabled": true 賬戶可用// },@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()//開啟配置.antMatchers("/admin/**").hasRole("admin")//路徑符合這個需要admin角色
// .antMatchers("user/**").hasAnyRole("admin", "user")//路徑符合這個,需要這兩個的任意一個.antMatchers("/user/**").access("hasAnyRole('user','admin')").anyRequest().authenticated()//其他請求,登錄后就可以訪問.and().formLogin()//表單登錄.loginProcessingUrl("/doLogin")//處理登錄請求的地址.loginPage("/login")//配置登錄頁面(實際上還是一個請求地址) 前后端分類不存在這種頁面 這里還是訪問的應該請求,會根據這請求去返回登錄頁面.usernameParameter("uname")//修改登錄的key.passwordParameter("passwd")//修改登錄的key.successHandler(new AuthenticationSuccessHandler() { //登錄成功的處理@Override// authentication保存了登錄成功后的信息public void onAuthenticationSuccess(HttpServletRequest req, 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", authentication.getPrincipal());out.write(new ObjectMapper().writeValueAsString(map));out.flush();out.close();}}).failureHandler(new AuthenticationFailureHandler() {//登錄失敗的處理@Override // e登錄失敗的異常public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp,AuthenticationException e) throws IOException, ServletException {resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.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", "登錄失敗!");}out.write(new ObjectMapper().writeValueAsString(map));out.flush();out.close();}}).permitAll().and().logout().logoutUrl("/logout") //配置注銷請求的地址.logoutSuccessHandler(new LogoutSuccessHandler() {//注銷成功后的回調@Overridepublic void onLogoutSuccess(HttpServletRequest req, 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", "注銷登錄成功!");out.write(new ObjectMapper().writeValueAsString(map));out.flush();out.close();}}).and().csrf().disable();/*** 權限不足處理*/http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandler() {@Overridepublic void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException {httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);Map<String, Object> failureMap = new HashMap<>();failureMap.put("code", 403);failureMap.put("msg", "權限不足!");httpServletResponse.getWriter().println(objectMapper.writeValueAsString(failureMap));}});
// /**
// * 未登陸處理
// */
// http.exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() {
// @Override
// public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
//
//
// httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
//
// Map<String, Object> failureMap = new HashMap<>();
// failureMap.put("code", 401);
// failureMap.put("msg", "請先登錄!");
//
// httpServletResponse.getWriter().println(objectMapper.writeValueAsString(failureMap));
//
// }
// });}
}
2.4多個HttpSecurity的配置(復雜業務場景下)—security
參考項目 spring-security-me/security
采用靜態內部類的方式 采用order設置優先級,數字越小,優先級越大
@Configuration
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true) //開啟方法安全
public class MultiHttpSecurityConfig {@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Autowiredprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.inMemoryAuthentication().withUser("javaboy").password("$2a$10$G3kVAJHvmRrr6sOj.j4xpO2Dsxl5EG8rHycPHFWyi9UMIhtdSH15u").roles("admin").and().withUser("").password("$2a$10$kWjG2GxWhm/2tN2ZBpi7bexXjUneIKFxIAaMYJzY7WcziZLCD4PZS").roles("user");}@Configuration@Order(1)public static class AdminSecurityConfig extends WebSecurityConfigurerAdapter{@Overrideprotected void configure(HttpSecurity http) throws Exception {http.antMatcher("/admin/**").authorizeRequests().anyRequest().hasAnyRole("admin");//只有這種格式的路徑才會去要求角色}}@Configurationpublic static class OtherSecurityConfig extends WebSecurityConfigurerAdapter{@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().anyRequest().authenticated().and().formLogin().loginProcessingUrl("/doLogin").permitAll().and().csrf().disable();}}
}
2.5配置方法安全
在Security上面加上
@EnableGlobalMethodSecurity(prePostEnabled = true,securedEnabled = true) //開啟方法安全
然后在方法上加PreAuthorize注解
@Service
public class MethodService {@PreAuthorize("hasRole('admin')")// 這個方法需要admin角色public String admin() {return "hello admin";}@Secured("ROLE_user") //需要user角色public String user() {return "hello user";}@PreAuthorize("hasAnyRole('admin','user')")//需要兩者之一public String hello() {return "hello hello";}
}
2.6基于數據庫的認證(基礎入門)-----sercuty-db/sercurity-dy
權限模型
權限實際開發模型
1.定義實體類user(繼承UserDetails)和role
security-demo.sql
public class User implements UserDetails {private Integer id;private String username;private String password;private Boolean enabled;private Boolean locked;private List<Role> roles;public List<Role> getRoles() {return roles;}public void setRoles(List<Role> roles) {this.roles = roles;}public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}// 返回用戶所有的角色@Overridepublic Collection<? extends GrantedAuthority> getAuthorities() {List<SimpleGrantedAuthority> authorities = new ArrayList<>();// 重新整理一下 角色認證要以ROLE_開始 數據庫沒有就要在這里手動拼接for (Role role : roles) {authorities.add(new SimpleGrantedAuthority(role.getName()));}return authorities;}@Overridepublic String getPassword() {return password;}public void setPassword(String password) {this.password = password;}@Overridepublic String getUsername() {return username;}// 賬戶是否未過期 目前數據庫沒有就直說true@Overridepublic boolean isAccountNonExpired() {return true;}// 賬戶是否未鎖定@Overridepublic boolean isAccountNonLocked() {return !locked;}// 密碼是否未過期@Overridepublic boolean isCredentialsNonExpired() {return true;}// 是否可用@Overridepublic boolean isEnabled() {return enabled;}public void setUsername(String username) {this.username = username;}public void setEnabled(Boolean enabled) {this.enabled = enabled;}public void setLocked(Boolean locked) {this.locked = locked;}
}
2.配置SecurityConfig
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@AutowiredUserService userService;@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}// 此處去調用數據庫的或者采用靜態數據@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userService);}@Overrideprotected void configure(HttpSecurity http) throws Exception {//對于不同的路徑要不同的角色 靜態配置http.authorizeRequests().antMatchers("/dba/**").hasRole("dba").antMatchers("/admin/**").hasRole("admin").antMatchers("/user/**").hasRole("user").anyRequest().authenticated().and().formLogin().permitAll().and().csrf().disable();}// 角色繼承的bean@BeanRoleHierarchy roleHierarchy() {RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();// 以前String hierarchy = "dba > admin admin > user";// 現在String hierarchy = "dba > admin \n admin > user";roleHierarchy.setHierarchy(hierarchy);return roleHierarchy;}
3.動態權限配置的Security寫法
1. 1.先定義MyFilter實現FilterInvocationSecurityMetadataSource
主要就是分析出需要哪些角色
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@AutowiredUserService userService;@AutowiredMyFilter myFilter;@AutowiredMyAccessDecisionManager myAccessDecisionManager;@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userService);}// @Bean
// RoleHierarchy roleHierarchy() {
// RoleHierarchyImpl roleHierarchy = new RoleHierarchyImpl();
// String hierarchy = "dba > admin \n admin > user";
// roleHierarchy.setHierarchy(hierarchy);
// return roleHierarchy;
// }
@Bean
@Override
protected UserDetailsService userDetailsService() {return super.userDetailsService();
}@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {@Overridepublic <O extends FilterSecurityInterceptor> O postProcess(O o) {o.setAccessDecisionManager(myAccessDecisionManager);o.setSecurityMetadataSource(myFilter);return o;}}).and().formLogin().permitAll().and().csrf().disable();}
}
2.編寫MyAccessDecisionManager繼承 AccessDecisionManager
@Component
public class MyAccessDecisionManager implements AccessDecisionManager {/**** @param authentication 當前用戶具備的角色* @param o* @param collection 當前路徑需要的角色,這里是在MyFiter處理后得到的* @throws AccessDeniedException* @throws InsufficientAuthenticationException*/@Overridepublic void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {for (ConfigAttribute attribute : collection) {if ("ROLE_login".equals(attribute.getAttribute())) {// 如果是返回的ROLE_login說明你請求的路徑不存在,所有判斷你有沒有登錄 登錄的就直接放行if (authentication instanceof AnonymousAuthenticationToken) {throw new AccessDeniedException("非法請求!");} else {return;}}// 獲取我具備的角色Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();// 做匹配for (GrantedAuthority authority : authorities) {if (authority.getAuthority().equals(attribute.getAttribute())) {return;}}}// 例如,我具備某些角色,但是此角色沒有此路徑的權限,那就是非要請求throw new AccessDeniedException("非法請求!");}@Overridepublic boolean supports(ConfigAttribute configAttribute) {return true;}@Overridepublic boolean supports(Class<?> aClass) {return true;}
}
3.1SecurityConfig的寫法
@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@AutowiredUserService userService;@AutowiredMyFilter myFilter;@AutowiredMyAccessDecisionManager myAccessDecisionManager;@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userService);}/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests().withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {//FilterSecurityInterceptor 攔截器@Overridepublic <O extends FilterSecurityInterceptor> O postProcess(O o) {o.setAccessDecisionManager(myAccessDecisionManager);o.setSecurityMetadataSource(myFilter);return o;}}).and().formLogin().permitAll().and().csrf().disable();}
}
2.7spring security整合oauth2—oauth2
2.7.1配置資源服務器 ResourceServerConfig
/*** 資源服務器*/
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {//指定資源id stateless配置基于令牌認證resources.resourceId("rid").stateless(true);}//此處角色路徑可以從數據庫加載// @Override
// public void configure(HttpSecurity http) throws Exception {
// // 路徑的角色
// http.authorizeRequests().antMatchers("/admin/**").hasRole("admin")
// .antMatchers("/user/**").hasRole("user")
// .anyRequest().authenticated();
// }// 從數據庫加載如下@AutowiredMyFilter myFilter;@AutowiredMyAccessDecisionManager myAccessDecisionManager;/*** @param http* @throws Exception*/@Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests().withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {@Overridepublic <O extends FilterSecurityInterceptor> O postProcess(O o) {o.setAccessDecisionManager(myAccessDecisionManager);o.setSecurityMetadataSource(myFilter);return o;}}).and().formLogin().permitAll().and().csrf().disable();}}
2.7.2授權服務器 AuthorizationServerConfig
/*** 授權服務器*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {// 支持password的認證模式@AutowiredAuthenticationManager authenticationManager;// 配置redis就會有@AutowiredRedisConnectionFactory redisConnectionFactory;// 密碼加密方式@AutowiredUserDetailsService userDetailsService;@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {//配置在內存中//配置認證模式//配置授權模式//資源id(名字)//配置的密碼123456clients.inMemory().withClient("password").authorizedGrantTypes("password", "refresh_token").accessTokenValiditySeconds(1800).resourceIds("rid").scopes("all").secret("$2a$10$LcM2.fVWzB50vitKLrPPDugS/owlp.qVVT5jA0EyJuFeez6S5hTkm");}// 配置令牌的存儲@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.tokenStore(new RedisTokenStore(redisConnectionFactory)) //.authenticationManager(authenticationManager).userDetailsService(userDetailsService);}@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.allowFormAuthenticationForClients();}}
2.7.3security配置文件
@Override@Beanprotected AuthenticationManager authenticationManager() throws Exception {return super.authenticationManager();}@Bean@Overrideprotected UserDetailsService userDetailsService() {return super.userDetailsService();}// 靜態的加載用戶
// @Override
// protected void configure(AuthenticationManagerBuilder auth) throws Exception {
// auth.inMemoryAuthentication()
// .withUser("javaboy").password("$2a$10$LcM2.fVWzB50vitKLrPPDugS/owlp.qVVT5jA0EyJuFeez6S5hTkm").roles("admin")
// .and()
// .withUser("finde")
// .password("$2a$10$kwLIAqAupvY87OM.O25.Yu1QKEXV1imAv7jWbDaQRFUFWSnSiDEwG")
// .roles("user");
// }
// 從數據庫加載用戶@AutowiredUserService userService;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userService);}//放開oauth相關的請求,不就行攔截@Overrideprotected void configure(HttpSecurity http) throws Exception {http.antMatcher("/oauth/**").authorizeRequests().antMatchers("/oauth/**").permitAll().and().csrf().disable();}
2.7.4 MyFilter
@Component
public class MyFilter implements FilterInvocationSecurityMetadataSource {// 做路徑匹配的 提供了路徑批評規則AntPathMatcher pathMatcher = new AntPathMatcher();@AutowiredMenuService menuService;/*** 分析請求地址 根據請求的地址,分析出需要哪些角色* @param o* @return* @throws IllegalArgumentException*/@Overridepublic Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {// 請求的地址String requestUrl = ((FilterInvocation) o).getRequestUrl();// 所有的菜單 ,這里可以給一個緩存List<Menu> allMenus = menuService.getAllMenus();for (Menu menu : allMenus) {// 如果請求地址批評上了if (pathMatcher.match(menu.getPattern(), requestUrl)) {List<Role> roles = menu.getRoles();String[] rolesStr = new String[roles.size()];//查看需要哪些角色 rolesStr,防止角色集合for (int i = 0; i < roles.size(); i++) {rolesStr[i] = roles.get(i).getName();}return SecurityConfig.createList(rolesStr);}}// 沒有匹配上路徑,這個就是標識符號,看在數據庫中沒有這個路徑,怎么處理return SecurityConfig.createList("ROLE_login");}@Overridepublic Collection<ConfigAttribute> getAllConfigAttributes() {return null;}@Overridepublic boolean supports(Class<?> aClass) {return true;}
}
2.7.5 MyAccessDecisionManager
@Component
public class MyAccessDecisionManager implements AccessDecisionManager {/**** @param authentication 當前用戶具備的角色* @param o* @param collection 當前路徑需要的角色,這里是在MyFiter處理后得到的* @throws AccessDeniedException* @throws InsufficientAuthenticationException*/@Overridepublic void decide(Authentication authentication, Object o, Collection<ConfigAttribute> collection) throws AccessDeniedException, InsufficientAuthenticationException {for (ConfigAttribute attribute : collection) {if ("ROLE_login".equals(attribute.getAttribute())) {// 如果是返回的ROLE_login說明你請求的路徑不存在,所有判斷你有沒有登錄 登錄的就直接放行if (authentication instanceof AnonymousAuthenticationToken) {throw new AccessDeniedException("非法請求!");} else {return;}}// 獲取我具備的角色Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();// 做匹配for (GrantedAuthority authority : authorities) {if (authority.getAuthority().equals(attribute.getAttribute())) {return;}}}// 例如,我具備某些角色,但是此角色沒有此路徑的權限,那就是非要請求throw new AccessDeniedException("非法請求!");}@Overridepublic boolean supports(ConfigAttribute configAttribute) {return true;}@Overridepublic boolean supports(Class<?> aClass) {return true;}
}
2.7.6 postman測試 -請求token
post http://127.0.0.1:8981/oauth/token
Body x-www-form-urlencoded
[{“key”:“username”,“value”:“admin”},
{“key”:“password”,“value”:“123”},
{“key”:“grant_type”,“value”:“password”},
{“key”:“client_id”,“value”:“password”},
{“key”:“scope”,“value”:“all”},
{“key”:“client_secret”,“value”:“123456”}]
{"username":"admin", "password":"123","grant_type":"password","client_id":"password","scope":"all","client_secret":"123456",
}
結果
{
“access_token”: “d1bdfd01-e06a-4b4e-a661-a49012da9afa”,
“token_type”: “bearer”,
“refresh_token”: “d31082b6-68a7-46b5-937a-62a24b186970”,
“expires_in”: 1325,
“scope”: “all”
}
換回新的token
{"grant_type":"refresh_token", "refresh_token":"d31082b6-68a7-46b5-937a-62a24b186970","grant_type":"password","client_secret":"123456",
}
2.8spring security支持json登錄—security-dy/security-db/oauth2
2.8.1重寫UsernamePasswordAuthenticationFilter方法
public class MyAuthenticationFilter extends UsernamePasswordAuthenticationFilter {@Overridepublic Authentication attemptAuthentication(HttpServletRequest request, HttpServletResponse response) throwsAuthenticationException {if (!request.getMethod().equals("POST")) {throw new AuthenticationServiceException("Authentication method not supported: " + request.getMethod());}if (request.getContentType().equals(MediaType.APPLICATION_JSON_VALUE)) {//說明用戶以 JSON 的形式傳遞的參數String username = null;String password = null;try {Map<String, String> map = new ObjectMapper().readValue(request.getInputStream(), Map.class);username = map.get("username");password = map.get("password");} catch (IOException e) {e.printStackTrace();}if (username == null) {username = "";}if (password == null) {password = "";}username = username.trim();UsernamePasswordAuthenticationToken authRequest = new UsernamePasswordAuthenticationToken(username, password);// Allow subclasses to set the "details" propertysetDetails(request, authRequest);return this.getAuthenticationManager().authenticate(authRequest);}return super.attemptAuthentication(request, response);}
2.8.2注入重寫的方法
在securityconfig中寫入一下文件
// 配置支持json登錄@BeanMyAuthenticationFilter myAuthenticationFilter() throws Exception {MyAuthenticationFilter filter = new MyAuthenticationFilter();filter.setAuthenticationManager(authenticationManagerBean());return filter;}/**** @param http* @throws Exception*/@Overrideprotected void configure(HttpSecurity http) throws Exception {http.addFilterAt(myAuthenticationFilter(), UsernamePasswordAuthenticationFilter.class);}
2.8.3配置登錄成功后的轉跳和失敗后轉跳
在myAuthenticationFilter中配置
此時成功和失敗的回調只能在fiter中配置,cnfigure中的配置是失效的
// 配置支持json登錄@BeanMyAuthenticationFilter myAuthenticationFilter() throws Exception {MyAuthenticationFilter filter = new MyAuthenticationFilter();filter.setAuthenticationManager(authenticationManagerBean());filter.setAuthenticationSuccessHandler(new AuthenticationSuccessHandler() { //登錄成功的處理@Override// authentication保存了登錄成功后的信息public void onAuthenticationSuccess(HttpServletRequest req, 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", authentication.getPrincipal());out.write(new ObjectMapper().writeValueAsString(map));out.flush();out.close();}});filter.setAuthenticationFailureHandler(new AuthenticationFailureHandler() {//登錄失敗的處理@Override // e登錄失敗的異常public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp,AuthenticationException e) throws IOException, ServletException {resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.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", "登錄失敗!");}out.write(new ObjectMapper().writeValueAsString(map));out.flush();out.close();}});return filter;}
2.9spring security整合jwt --jwt-demo
2.9.1 JwtLoginFilter 登錄的時候給用戶token
public class JwtLoginFilter extends AbstractAuthenticationProcessingFilter {// 實現構造方法/**** @param defaultFilterProcessesUrl* @param authenticationManager*/public JwtLoginFilter(String defaultFilterProcessesUrl, AuthenticationManager authenticationManager) {super(new AntPathRequestMatcher(defaultFilterProcessesUrl));setAuthenticationManager(authenticationManager);}/*** 提取用戶名和密碼去做登錄** @param req* @param httpServletResponse* @return* @throws AuthenticationException* @throws IOException*/@Overridepublic Authentication attemptAuthentication(HttpServletRequest req, HttpServletResponse httpServletResponse)throws AuthenticationException, IOException {// 為了獲取登錄的數據轉換成userUser user = new ObjectMapper().readValue(req.getInputStream(), User.class);return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));}// 登錄成功的回調 生成jwt@Overrideprotected void successfulAuthentication(HttpServletRequest request, HttpServletResponse resp,FilterChain chain, Authentication authResult) throws IOException, ServletException {Collection<? extends GrantedAuthority> authorities = authResult.getAuthorities();//獲取登錄用戶的角色StringBuffer sb = new StringBuffer();for (GrantedAuthority authority : authorities) {//獲取當前角色sb.append(authority.getAuthority()).append(",");}// 生成jwt的tokenString jwt = Jwts.builder().claim("authorities", sb)// 用戶的角色.setSubject(authResult.getName()) // 主題.setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 1000)) // 過期時間.signWith(SignatureAlgorithm.HS512, "findme") // 簽名的算法.compact();Map<String, String> map = new HashMap<>();map.put("token", jwt);map.put("msg", "登錄成功");resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.getWriter();out.write(new ObjectMapper().writeValueAsString(map));out.flush();out.close();}// 登錄失敗/***** @param req* @param resp* @param failed* @throws IOException* @throws ServletException 登錄失敗的異常,根據異常判斷失敗的原因*/@Overrideprotected void unsuccessfulAuthentication(HttpServletRequest req, HttpServletResponse resp,AuthenticationException failed) throws IOException, ServletException {Map<String, String> map = new HashMap<>();map.put("msg", "登錄失敗");resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.getWriter();out.write(new ObjectMapper().writeValueAsString(map));out.flush();out.close();}
2.9.2. 訪問系統的時候效驗token
public class JwtFilter extends GenericFilterBean {/*** 用戶每次登錄的時候校驗token** @param servletRequest* @param servletResponse* @param filterChain* @throws IOException* @throws ServletException*/@Overridepublic void doFilter(ServletRequest servletRequest, ServletResponse servletResponse,FilterChain filterChain) throws IOException, ServletException {HttpServletRequest req = (HttpServletRequest) servletRequest;// token 放在很多地方都可以,此處是默認把token放到請求頭中String jwtToken = req.getHeader("authorization");// 解析tokenJws<Claims> jws = Jwts.parser().setSigningKey("findme") // 生成token的簽名.parseClaimsJws(jwtToken.replace("Bearer", "")); // 前端的token會自動加一個Bearer,此處需要去掉Claims claims = jws.getBody(); // 登錄的信息String username = claims.getSubject();// 用戶名 剛才在生成的時候放入了// 拿到登錄的角色后要轉換成一個list集合解析 此處是當前用戶的角色List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList((String) claims.get("authorities"));// new 一個新的tokenUsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, null, authorities);SecurityContextHolder.getContext().setAuthentication(token);// 對過濾器放行filterChain.doFilter(servletRequest,servletResponse);}
2.9.3增加security的相關配置 configure_(HttpSecurity http) _
// jwt 相關配置http.authorizeRequests().antMatchers(HttpMethod.POST, "/login").permitAll().anyRequest().authenticated().and()// 登錄的過濾器.addFilterBefore(new JwtLoginFilter("/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)// 做校驗的過濾器.addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class).csrf().disable();
2.10 oauth2 整合jwt+swagger —swcurity-swagger/ 松哥例子swagger-jwt
注意在引入依賴的時候引入cloud相關的
2.10.1.AccessTokenConfig
package com.find.securityswagger.auth;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;/*** @ClassName AccessTokenConfig* @Description token* @Author find me* @Date 2020/6/25 0025 20:37* @Version 1.0*/
@Configuration
public class AccessTokenConfig {// TokenStore 我們使用 JwtTokenStore 這個實例。// 使用了 JWT,access_token 實際上就不用存儲了(無狀態登錄,服務端不需要保存信息),// 因為用戶的所有信息都在 jwt 里邊,所以這里配置的 JwtTokenStore 本質上并不是做存儲。@BeanTokenStore tokenStore() {return new JwtTokenStore(jwtAccessTokenConverter());}// 另外我們還提供了一個 JwtAccessTokenConverter,// 這個 JwtAccessTokenConverter 可以實現將用戶信息和 JWT 進行轉換(將用戶信息轉為 jwt 字符串,或者從 jwt 字符串提取出用戶信息)。// 另外,在 JWT 字符串生成的時候,我們需要一個簽名,這個簽名需要自己保存好。@BeanJwtAccessTokenConverter jwtAccessTokenConverter() {JwtAccessTokenConverter converter = new JwtAccessTokenConverter();converter.setSigningKey("findme");return converter;}
}
2.10.2AuthorizationServer
package com.find.securityswagger.auth;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.ClientDetailsService;
import org.springframework.security.oauth2.provider.token.AuthorizationServerTokenServices;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancerChain;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;import java.util.Arrays;/*** @ClassName JwtAccessTokenConverter* @Description 將用戶信息和 JWT 進行轉換* @Author find me* @Date 2020/6/25 0025 20:39* @Version 1.0*/
@EnableAuthorizationServer
@Configuration
public class AuthorizationServer extends AuthorizationServerConfigurerAdapter {@AutowiredTokenStore tokenStore;@AutowiredClientDetailsService clientDetailsService;@AutowiredAuthenticationManager authenticationManager;@AutowiredPasswordEncoder passwordEncoder;@AutowiredJwtAccessTokenConverter jwtAccessTokenConverter;//主要用來配置 Token 的一些基本信息,// 例如 Token 是否支持刷新、Token 的存儲位置、Token 的有效期以及刷新 Token 的有效期等等。// Token 有效期這個好理解,刷新 Token 的有效期我說一下,// 當 Token 快要過期的時候,我們需要獲取一個新的 Token,在獲取新的 Token 時候,// 需要有一個憑證信息,這個憑證信息不是舊的 Token,而是另外一個 refresh_token,這個 refresh_token 也是有有效期的。@BeanAuthorizationServerTokenServices tokenServices() {DefaultTokenServices services = new DefaultTokenServices();services.setClientDetailsService(clientDetailsService);services.setSupportRefreshToken(true);services.setTokenStore(tokenStore);services.setAccessTokenValiditySeconds(60 * 60 * 24 * 2);services.setRefreshTokenValiditySeconds(60 * 60 * 24 * 7);TokenEnhancerChain tokenEnhancerChain = new TokenEnhancerChain();tokenEnhancerChain.setTokenEnhancers(Arrays.asList(jwtAccessTokenConverter));services.setTokenEnhancer(tokenEnhancerChain);return services;}//用來配置令牌端點的安全約束,也就是這個端點誰能訪問,誰不能訪問。@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.allowFormAuthenticationForClients();}//用來配置客戶端的詳細信息@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("findme").secret(passwordEncoder.encode("123")) //.resourceIds("rid")//資源id.authorizedGrantTypes("password", "refresh_token")//授權類型.scopes("all").redirectUris("http://localhost:6004/index.html");//重定向 uri}// 這里用來配置令牌的訪問端點和令牌服務。@Overridepublic void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {endpoints.authenticationManager(authenticationManager).tokenServices(tokenServices());}
}
2.10.3ResourceServerConfig
package com.find.securityswagger.auth;import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.ObjectPostProcessor;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.web.access.intercept.FilterSecurityInterceptor;/*** @ClassName ResourceServerConfig* @Description* @Author find me* @Date 2020/6/25 0025 20:41* @Version 1.0*/
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {@AutowiredTokenStore tokenStore;//首先在 configure 方法中配置資源 ID 和 TokenStore,這里配置好之后,// 會自動調用 JwtAccessTokenConverter 將 jwt 解析出來,jwt 里邊就// 包含了用戶的基本信息,所以就不用遠程校驗 access_token 了。@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {//指定資源id stateless配置基于令牌認證
// resources.resourceId("rid").stateless(true);resources.resourceId("rid").tokenStore(tokenStore);}@AutowiredMyFilter myFilter;@AutowiredMyAccessDecisionManager myAccessDecisionManager;/*** @param http* @throws Exception*/@Overridepublic void configure(HttpSecurity http) throws Exception {http.authorizeRequests().withObjectPostProcessor(new ObjectPostProcessor<FilterSecurityInterceptor>() {@Overridepublic <O extends FilterSecurityInterceptor> O postProcess(O o) {o.setAccessDecisionManager(myAccessDecisionManager);o.setSecurityMetadataSource(myFilter);return o;}}).and().formLogin().permitAll().and().csrf().disable();}
}
2.10.4 GlobalCorsConfiguration —支持跨域
package com.find.securityswagger.swaggerconfig;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.cors.CorsConfiguration;
import org.springframework.web.cors.UrlBasedCorsConfigurationSource;
import org.springframework.web.filter.CorsFilter;/*** @ClassName GlobalCorsConfiguration* @Description 支持跨域* @Author find me* @Date 2020/6/25 0025 21:36* @Version 1.0*/
@Configuration
public class GlobalCorsConfiguration {@Beanpublic CorsFilter corsFilter() {CorsConfiguration corsConfiguration = new CorsConfiguration();corsConfiguration.setAllowCredentials(true);corsConfiguration.addAllowedOrigin("*");corsConfiguration.addAllowedHeader("*");corsConfiguration.addAllowedMethod("*");UrlBasedCorsConfigurationSource urlBasedCorsConfigurationSource = new UrlBasedCorsConfigurationSource();urlBasedCorsConfigurationSource.registerCorsConfiguration("/**", corsConfiguration);return new CorsFilter(urlBasedCorsConfigurationSource);}
}
package com.find.securityswagger.swaggerconfig;import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.OAuthBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.*;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spi.service.contexts.SecurityContext;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;import java.util.Arrays;
import java.util.List;/*** @ClassName Swagger2Config* @Description swagger* @Author find me* @Date 2020/6/25 0025 21:19* @Version 1.0*/
@Configuration
@EnableSwagger2
public class Swagger2Config {
// // 手動添加token的方式
// @Bean
// Docket docket() {
// return new Docket(DocumentationType.SWAGGER_2)
// .select()
// .apis(RequestHandlerSelectors.basePackage("com.find.securityswagger.controller"))
// .paths(PathSelectors.any())
// .build()
// .securityContexts(Arrays.asList(securityContexts()))
// .securitySchemes(Arrays.asList(securitySchemes()))
// .apiInfo(new ApiInfoBuilder()
// .description("接口文檔的描述信息")
// .title("微人事項目接口文檔")
// .contact(new Contact("javaboy","https://www.yuque.com/findme","2354827879@qq.com"))
// .version("v1.0")
// .license("Apache2.0")
// .build());
// }
// //通過 securitySchemes 來配置全局參數,這里的配置是一個名為 Authorization 的請求頭(OAuth2 中需要攜帶的請求頭)。
// private SecurityScheme securitySchemes() {
// return new ApiKey("Authorization", "Authorization", "header");
// }
//
// // 則用來配置有哪些請求需要攜帶 Token,這里我們配置了所有請求。
// private SecurityContext securityContexts() {
// return SecurityContext.builder()
// .securityReferences(defaultAuth())
// .forPaths(PathSelectors.any())
// .build();
// }
//
// // 參數
// private List<SecurityReference> defaultAuth() {
// AuthorizationScope authorizationScope = new AuthorizationScope("xxx", "描述信息");
// AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
// authorizationScopes[0] = authorizationScope;
// return Arrays.asList(new SecurityReference("Authorization", authorizationScopes));
// }// 可以在頁面去配置整個登錄信息@BeanDocket docket() {return new Docket(DocumentationType.SWAGGER_2).select().apis(RequestHandlerSelectors.basePackage("com.find.securityswagger.controller")).paths(PathSelectors.any()).build().securityContexts(Arrays.asList(securityContext())).securitySchemes(Arrays.asList(securityScheme())).apiInfo(new ApiInfoBuilder().description("接口文檔的描述信息").title("find me demo ").contact(new Contact("findme","https://www.yuque.com/findme","2354827879@qq.com")).version("v1.0").license("Apache2.0").build());}private AuthorizationScope[] scopes() {return new AuthorizationScope[]{new AuthorizationScope("all", "all scope")};}// 構建時即得配置 token 的獲取地址。private SecurityScheme securityScheme() {GrantType grant = new ResourceOwnerPasswordCredentialsGrant("http://127.0.0.1:6004/oauth/token");return new OAuthBuilder().name("OAuth2").grantTypes(Arrays.asList(grant)).scopes(Arrays.asList(scopes())).build();}private SecurityContext securityContext() {return SecurityContext.builder().securityReferences(Arrays.asList(new SecurityReference("OAuth2", scopes()))).forPaths(PathSelectors.any()).build();}
}
swagger的兩種配置的效果如下
輸入 Bearer ${token}
postman測試參數如下 先獲取token,在傳遞token
2.11configure其他配置
@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()//開啟配置.antMatchers("/admin/**").hasRole("admin")//路徑符合這個需要admin角色
// .antMatchers("user/**").hasAnyRole("admin", "user")//路徑符合這個,需要這兩個的任意一個.antMatchers("/user/**").access("hasAnyRole('user','admin')").anyRequest().authenticated()//其他請求,登錄后就可以訪問.and().formLogin()//表單登錄.loginProcessingUrl("/doLogin")//處理登錄請求的地址.loginPage("/login")//配置登錄頁面(實際上還是一個請求地址) 前后端分類不存在這種頁面 這里還是訪問的應該請求,會根據這請求去返回登錄頁面.usernameParameter("uname")//修改登錄的key.passwordParameter("passwd")//修改登錄的key.successHandler(new AuthenticationSuccessHandler() { //登錄成功的處理@Override// authentication保存了登錄成功后的信息public void onAuthenticationSuccess(HttpServletRequest req, 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", authentication.getPrincipal());out.write(new ObjectMapper().writeValueAsString(map));out.flush();out.close();}}).failureHandler(new AuthenticationFailureHandler() {//登錄失敗的處理@Override // e登錄失敗的異常public void onAuthenticationFailure(HttpServletRequest req, HttpServletResponse resp,AuthenticationException e) throws IOException, ServletException {resp.setContentType("application/json;charset=utf-8");PrintWriter out = resp.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", "登錄失敗!");}out.write(new ObjectMapper().writeValueAsString(map));out.flush();out.close();}}).permitAll().and().logout().logoutUrl("/logout") //配置注銷請求的地址.logoutSuccessHandler(new LogoutSuccessHandler() {//注銷成功后的回調@Overridepublic void onLogoutSuccess(HttpServletRequest req, 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", "注銷登錄成功!");out.write(new ObjectMapper().writeValueAsString(map));out.flush();out.close();}}).and().csrf().disable();/*** 權限不足處理*/http.exceptionHandling().accessDeniedHandler(new AccessDeniedHandler() {@Overridepublic void handle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AccessDeniedException e) throws IOException {httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);Map<String, Object> failureMap = new HashMap<>();failureMap.put("code", 403);failureMap.put("msg", "權限不足!");httpServletResponse.getWriter().println(objectMapper.writeValueAsString(failureMap));}});
// /**
// * 未登陸處理
// */
// http.exceptionHandling().authenticationEntryPoint(new AuthenticationEntryPoint() {
// @Override
// public void commence(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException {
//
//
// httpServletResponse.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);
//
// Map<String, Object> failureMap = new HashMap<>();
// failureMap.put("code", 401);
// failureMap.put("msg", "請先登錄!");
//
// httpServletResponse.getWriter().println(objectMapper.writeValueAsString(failureMap));
//
// }
// });
//
總結
以上是生活随笔為你收集整理的1.spring security简单的demo-适合萌新的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 北斗三号b1c频点带宽_重磅北斗星通新一
- 下一篇: 武大校长开学典礼盛赞华为Mate60 P