日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 综合教程 >内容正文

综合教程

1.spring security简单的demo-适合萌新

發(fā)布時(shí)間:2023/12/3 综合教程 34 生活家
生活随笔 收集整理的這篇文章主要介紹了 1.spring security简单的demo-适合萌新 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 1.spring security入門
    • 1.創(chuàng)建項(xiàng)目,引入依賴
    • 2.security的其他配置方式
      • 2.2基于內(nèi)存
      • 2.3HttpSecurity(入門配置此文件)
      • 2.4多個(gè)HttpSecurity的配置(復(fù)雜業(yè)務(wù)場(chǎng)景下)---security
      • 2.5配置方法安全
      • 2.6基于數(shù)據(jù)庫(kù)的認(rèn)證(基礎(chǔ)入門)-----sercuty-db/sercurity-dy
        • 1.定義實(shí)體類user(繼承UserDetails)和role
        • 2.配置SecurityConfig
        • 3.動(dòng)態(tài)權(quán)限配置的Security寫法
          • 1. 1.先定義MyFilter實(shí)現(xiàn)FilterInvocationSecurityMetadataSource
          • 3.1SecurityConfig的寫法
      • 2.7spring security整合oauth2---oauth2
        • 2.7.1配置資源服務(wù)器 ResourceServerConfig
        • 2.7.2授權(quán)服務(wù)器 AuthorizationServerConfig
        • 2.7.3security配置文件
        • 2.7.4 MyFilter
        • 2.7.5 MyAccessDecisionManager
        • 2.7.6 postman測(cè)試 -請(qǐng)求token
      • 2.8spring security支持json登錄---security-dy/security-db/oauth2
        • 2.8.1重寫UsernamePasswordAuthenticationFilter方法
        • 2.8.2注入重寫的方法
        • 2.8.3配置登錄成功后的轉(zhuǎn)跳和失敗后轉(zhuǎn)跳
      • 2.9spring security整合jwt --jwt-demo
        • 2.9.1 JwtLoginFilter _登錄的時(shí)候給用戶token_
        • 2.9.2. _訪問(wèn)系統(tǒng)的時(shí)候效驗(yàn)token_
        • 2.9.3增加security的相關(guān)配置 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 數(shù)據(jù)庫(kù)驗(yàn)證的文件

密碼是123或者123456/ 可以使用 new BCryptPasswordEncoder_().encode(“123”)_;加密出來(lái)
模板項(xiàng)目地址https://gitee.com/find_me/java-findme

1.創(chuàng)建項(xiàng)目,引入依賴

  <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>

引入依賴后,項(xiàng)目中所有的接口就會(huì)被保護(hù)起來(lái),項(xiàng)目默認(rèn)用戶名為user,密碼為啟動(dòng)后隨即生成的,在控制臺(tái)打印的密碼

2.security的其他配置方式

spring:security:user: name: find mepassword: 123456roles: admin

2.2基于內(nèi)存

當(dāng)然,開發(fā)者也可以自定義類繼承自WebSecurityConfigurerAdapter ,進(jìn)而實(shí)現(xiàn)對(duì) Spring Security
更多的自定義配置,例如基于內(nèi)存的認(rèn)證,配置方式如下:

@Configuration public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter { // 密碼不加密的配置 ,過(guò)時(shí)的方法@Bean //PasswordEncoder passwordEncoder () { //return NoOpPasswordEncoder. getlnstance () ; // }// 密碼需要加密@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}//基于內(nèi)存的配置@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)方法,在該方法中配直兩個(gè)用戶,一個(gè)用戶名是
admin,密碼123 ,具備兩個(gè)角色 ADMIN USER 另一個(gè)用戶名是 findme,密碼是 123 ,具備一個(gè)角色USER
Spring Security 本是 0.6 Spring Security 中引入了 多種密碼加密方式,開發(fā)者必須指定其中一種, NoOpPasswordEncoder ,即不對(duì)密碼進(jìn)行加密。

注意:基于配置和內(nèi)存的方式在配置角色的時(shí)候不需要添加"ROLE_".基于數(shù)據(jù)庫(kù)的需要

2.3HttpSecurity(入門配置此文件)

根據(jù)實(shí)際情況進(jìn)行角色配置

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {@Resourceprivate ObjectMapper objectMapper;@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}// 配置登錄的賬號(hào)@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.請(qǐng)求路徑角色// 2.配置表單登錄// 3.配置登錄成功,失敗或者登出的處理方式// authentication里面存放登錄成功后的信息//      {//            "password": null, 密碼//             "username": "javaboy",//             "authorities": [ 具備的角色//            {//                "authority": "ROLE_admin" //            }//        ],//            "accountNonExpired": true, 賬戶沒(méi)有過(guò)期,//                "accountNonLocked": true, 賬戶沒(méi)有鎖定//                "credentialsNonExpired": true, 密碼沒(méi)有過(guò)期//                "enabled": true 賬戶可用//        },@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()//開啟配置.antMatchers("/admin/**").hasRole("admin")//路徑符合這個(gè)需要admin角色
//                .antMatchers("user/**").hasAnyRole("admin", "user")//路徑符合這個(gè),需要這兩個(gè)的任意一個(gè).antMatchers("/user/**").access("hasAnyRole('user','admin')").anyRequest().authenticated()//其他請(qǐng)求,登錄后就可以訪問(wèn).and().formLogin()//表單登錄.loginProcessingUrl("/doLogin")//處理登錄請(qǐng)求的地址.loginPage("/login")//配置登錄頁(yè)面(實(shí)際上還是一個(gè)請(qǐng)求地址) 前后端分類不存在這種頁(yè)面 這里還是訪問(wèn)的應(yīng)該請(qǐng)求,會(huì)根據(jù)這請(qǐng)求去返回登錄頁(yè)面.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", "用戶名或密碼輸入錯(cuò)誤,登錄失敗!");} else if (e instanceof DisabledException) {map.put("msg", "賬戶被禁用,登錄失敗!");} else if (e instanceof AccountExpiredException) {map.put("msg", "賬戶過(guò)期,登錄失敗!");} else if (e instanceof CredentialsExpiredException) {map.put("msg", "密碼過(guò)期,登錄失敗!");} else {map.put("msg", "登錄失敗!");}out.write(new ObjectMapper().writeValueAsString(map));out.flush();out.close();}}).permitAll().and().logout().logoutUrl("/logout") //配置注銷請(qǐng)求的地址.logoutSuccessHandler(new LogoutSuccessHandler() {//注銷成功后的回調(diào)@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();/*** 權(quán)限不足處理*/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", "權(quán)限不足!");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", "請(qǐng)先登錄!");
//
//                httpServletResponse.getWriter().println(objectMapper.writeValueAsString(failureMap));
//
//            }
//        });}
}

2.4多個(gè)HttpSecurity的配置(復(fù)雜業(yè)務(wù)場(chǎng)景下)—security

參考項(xiàng)目 spring-security-me/security
采用靜態(tài)內(nèi)部類的方式 采用order設(shè)置優(yōu)先級(jí),數(shù)字越小,優(yōu)先級(jí)越大

@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");//只有這種格式的路徑才會(huì)去要求角色}}@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')")// 這個(gè)方法需要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基于數(shù)據(jù)庫(kù)的認(rèn)證(基礎(chǔ)入門)-----sercuty-db/sercurity-dy

權(quán)限模型

權(quán)限實(shí)際開發(fā)模型

1.定義實(shí)體類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<>();// 重新整理一下 角色認(rèn)證要以ROLE_開始 數(shù)據(jù)庫(kù)沒(méi)有就要在這里手動(dòng)拼接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;}// 賬戶是否未過(guò)期 目前數(shù)據(jù)庫(kù)沒(méi)有就直說(shuō)true@Overridepublic boolean isAccountNonExpired() {return true;}// 賬戶是否未鎖定@Overridepublic boolean isAccountNonLocked() {return !locked;}// 密碼是否未過(guò)期@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();}// 此處去調(diào)用數(shù)據(jù)庫(kù)的或者采用靜態(tài)數(shù)據(jù)@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userService);}@Overrideprotected void configure(HttpSecurity http) throws Exception {//對(duì)于不同的路徑要不同的角色 靜態(tài)配置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";// 現(xiàn)在String hierarchy = "dba > admin \n admin > user";roleHierarchy.setHierarchy(hierarchy);return roleHierarchy;}	

3.動(dòng)態(tài)權(quán)限配置的Security寫法

1. 1.先定義MyFilter實(shí)現(xiàn)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 當(dāng)前用戶具備的角色* @param o* @param collection  當(dāng)前路徑需要的角色,這里是在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說(shuō)明你請(qǐng)求的路徑不存在,所有判斷你有沒(méi)有登錄 登錄的就直接放行if (authentication instanceof AnonymousAuthenticationToken) {throw new AccessDeniedException("非法請(qǐng)求!");} else {return;}}// 獲取我具備的角色Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();// 做匹配for (GrantedAuthority authority : authorities) {if (authority.getAuthority().equals(attribute.getAttribute())) {return;}}}// 例如,我具備某些角色,但是此角色沒(méi)有此路徑的權(quán)限,那就是非要請(qǐng)求throw new AccessDeniedException("非法請(qǐng)求!");}@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配置資源服務(wù)器 ResourceServerConfig

/*** 資源服務(wù)器*/
@Configuration
@EnableResourceServer
public class ResourceServerConfig extends ResourceServerConfigurerAdapter {@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {//指定資源id stateless配置基于令牌認(rèn)證resources.resourceId("rid").stateless(true);}//此處角色路徑可以從數(shù)據(jù)庫(kù)加載//    @Override
//    public void configure(HttpSecurity http) throws Exception {
//        // 路徑的角色
//        http.authorizeRequests().antMatchers("/admin/**").hasRole("admin")
//                .antMatchers("/user/**").hasRole("user")
//                .anyRequest().authenticated();
//    }// 從數(shù)據(jù)庫(kù)加載如下@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授權(quán)服務(wù)器 AuthorizationServerConfig


/*** 授權(quán)服務(wù)器*/
@Configuration
@EnableAuthorizationServer
public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {// 支持password的認(rèn)證模式@AutowiredAuthenticationManager authenticationManager;// 配置redis就會(huì)有@AutowiredRedisConnectionFactory redisConnectionFactory;// 密碼加密方式@AutowiredUserDetailsService userDetailsService;@BeanPasswordEncoder passwordEncoder() {return new BCryptPasswordEncoder();}@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {//配置在內(nèi)存中//配置認(rèn)證模式//配置授權(quán)模式//資源id(名字)//配置的密碼123456clients.inMemory().withClient("password").authorizedGrantTypes("password", "refresh_token").accessTokenValiditySeconds(1800).resourceIds("rid").scopes("all").secret("$2a$10$LcM2.fVWzB50vitKLrPPDugS/owlp.qVVT5jA0EyJuFeez6S5hTkm");}// 配置令牌的存儲(chǔ)@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();}//  靜態(tài)的加載用戶
//    @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");
//    }
// 從數(shù)據(jù)庫(kù)加載用戶@AutowiredUserService userService;@Overrideprotected void configure(AuthenticationManagerBuilder auth) throws Exception {auth.userDetailsService(userService);}//放開oauth相關(guān)的請(qǐng)求,不就行攔截@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 {// 做路徑匹配的 提供了路徑批評(píng)規(guī)則AntPathMatcher pathMatcher = new AntPathMatcher();@AutowiredMenuService menuService;/*** 分析請(qǐng)求地址 根據(jù)請(qǐng)求的地址,分析出需要哪些角色* @param o* @return* @throws IllegalArgumentException*/@Overridepublic Collection<ConfigAttribute> getAttributes(Object o) throws IllegalArgumentException {// 請(qǐng)求的地址String requestUrl = ((FilterInvocation) o).getRequestUrl();// 所有的菜單 ,這里可以給一個(gè)緩存List<Menu> allMenus = menuService.getAllMenus();for (Menu menu : allMenus) {// 如果請(qǐng)求地址批評(píng)上了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);}}// 沒(méi)有匹配上路徑,這個(gè)就是標(biāo)識(shí)符號(hào),看在數(shù)據(jù)庫(kù)中沒(méi)有這個(gè)路徑,怎么處理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 當(dāng)前用戶具備的角色* @param o* @param collection  當(dāng)前路徑需要的角色,這里是在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說(shuō)明你請(qǐng)求的路徑不存在,所有判斷你有沒(méi)有登錄 登錄的就直接放行if (authentication instanceof AnonymousAuthenticationToken) {throw new AccessDeniedException("非法請(qǐng)求!");} else {return;}}// 獲取我具備的角色Collection<? extends GrantedAuthority> authorities = authentication.getAuthorities();// 做匹配for (GrantedAuthority authority : authorities) {if (authority.getAuthority().equals(attribute.getAttribute())) {return;}}}// 例如,我具備某些角色,但是此角色沒(méi)有此路徑的權(quán)限,那就是非要請(qǐng)求throw new AccessDeniedException("非法請(qǐng)求!");}@Overridepublic boolean supports(ConfigAttribute configAttribute) {return true;}@Overridepublic boolean supports(Class<?> aClass) {return true;}
}

2.7.6 postman測(cè)試 -請(qǐng)求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",
}

結(jié)果
{
“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)) {//說(shuō)明用戶以 JSON 的形式傳遞的參數(shù)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配置登錄成功后的轉(zhuǎn)跳和失敗后轉(zhuǎn)跳

在myAuthenticationFilter中配置
此時(shí)成功和失敗的回調(diào)只能在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", "用戶名或密碼輸入錯(cuò)誤,登錄失敗!");} else if (e instanceof DisabledException) {map.put("msg", "賬戶被禁用,登錄失敗!");} else if (e instanceof AccountExpiredException) {map.put("msg", "賬戶過(guò)期,登錄失敗!");} else if (e instanceof CredentialsExpiredException) {map.put("msg", "密碼過(guò)期,登錄失敗!");} 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 登錄的時(shí)候給用戶token

public class JwtLoginFilter extends AbstractAuthenticationProcessingFilter {// 實(shí)現(xiàn)構(gòu)造方法/**** @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 {// 為了獲取登錄的數(shù)據(jù)轉(zhuǎn)換成userUser user = new ObjectMapper().readValue(req.getInputStream(), User.class);return getAuthenticationManager().authenticate(new UsernamePasswordAuthenticationToken(user.getUsername(), user.getPassword()));}// 登錄成功的回調(diào) 生成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) {//獲取當(dāng)前角色sb.append(authority.getAuthority()).append(",");}// 生成jwt的tokenString jwt = Jwts.builder().claim("authorities", sb)// 用戶的角色.setSubject(authResult.getName()) // 主題.setExpiration(new Date(System.currentTimeMillis() + 60 * 60 * 1000)) // 過(guò)期時(shí)間.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 登錄失敗的異常,根據(jù)異常判斷失敗的原因*/@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. 訪問(wèn)系統(tǒng)的時(shí)候效驗(yàn)token

public class JwtFilter extends GenericFilterBean {/*** 用戶每次登錄的時(shí)候校驗(yàn)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 放在很多地方都可以,此處是默認(rèn)把token放到請(qǐng)求頭中String jwtToken = req.getHeader("authorization");// 解析tokenJws<Claims> jws = Jwts.parser().setSigningKey("findme") // 生成token的簽名.parseClaimsJws(jwtToken.replace("Bearer", "")); // 前端的token會(huì)自動(dòng)加一個(gè)Bearer,此處需要去掉Claims claims = jws.getBody(); // 登錄的信息String username = claims.getSubject();// 用戶名 剛才在生成的時(shí)候放入了// 拿到登錄的角色后要轉(zhuǎn)換成一個(gè)list集合解析  此處是當(dāng)前用戶的角色List<GrantedAuthority> authorities = AuthorityUtils.commaSeparatedStringToAuthorityList((String) claims.get("authorities"));// new 一個(gè)新的tokenUsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(username, null, authorities);SecurityContextHolder.getContext().setAuthentication(token);// 對(duì)過(guò)濾器放行filterChain.doFilter(servletRequest,servletResponse);}

2.9.3增加security的相關(guān)配置 configure_(HttpSecurity http) _

 // jwt 相關(guān)配置http.authorizeRequests().antMatchers(HttpMethod.POST, "/login").permitAll().anyRequest().authenticated().and()// 登錄的過(guò)濾器.addFilterBefore(new JwtLoginFilter("/login", authenticationManager()), UsernamePasswordAuthenticationFilter.class)// 做校驗(yàn)的過(guò)濾器.addFilterBefore(new JwtFilter(), UsernamePasswordAuthenticationFilter.class).csrf().disable();

2.10 oauth2 整合jwt+swagger —swcurity-swagger/ 松哥例子swagger-jwt

注意在引入依賴的時(shí)候引入cloud相關(guān)的

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 這個(gè)實(shí)例。// 使用了 JWT,access_token 實(shí)際上就不用存儲(chǔ)了(無(wú)狀態(tài)登錄,服務(wù)端不需要保存信息),// 因?yàn)橛脩舻乃行畔⒍荚?jwt 里邊,所以這里配置的 JwtTokenStore 本質(zhì)上并不是做存儲(chǔ)。@BeanTokenStore tokenStore() {return new JwtTokenStore(jwtAccessTokenConverter());}// 另外我們還提供了一個(gè) JwtAccessTokenConverter,// 這個(gè) JwtAccessTokenConverter 可以實(shí)現(xiàn)將用戶信息和 JWT 進(jìn)行轉(zhuǎn)換(將用戶信息轉(zhuǎn)為 jwt 字符串,或者從 jwt 字符串提取出用戶信息)。// 另外,在 JWT 字符串生成的時(shí)候,我們需要一個(gè)簽名,這個(gè)簽名需要自己保存好。@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 進(jìn)行轉(zhuǎn)換* @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;//主要用來(lái)配置 Token 的一些基本信息,// 例如 Token 是否支持刷新、Token 的存儲(chǔ)位置、Token 的有效期以及刷新 Token 的有效期等等。// Token 有效期這個(gè)好理解,刷新 Token 的有效期我說(shuō)一下,// 當(dāng) Token 快要過(guò)期的時(shí)候,我們需要獲取一個(gè)新的 Token,在獲取新的 Token 時(shí)候,// 需要有一個(gè)憑證信息,這個(gè)憑證信息不是舊的 Token,而是另外一個(gè) refresh_token,這個(gè) 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;}//用來(lái)配置令牌端點(diǎn)的安全約束,也就是這個(gè)端點(diǎn)誰(shuí)能訪問(wèn),誰(shuí)不能訪問(wèn)。@Overridepublic void configure(AuthorizationServerSecurityConfigurer security) throws Exception {security.allowFormAuthenticationForClients();}//用來(lái)配置客戶端的詳細(xì)信息@Overridepublic void configure(ClientDetailsServiceConfigurer clients) throws Exception {clients.inMemory().withClient("findme").secret(passwordEncoder.encode("123")) //.resourceIds("rid")//資源id.authorizedGrantTypes("password", "refresh_token")//授權(quán)類型.scopes("all").redirectUris("http://localhost:6004/index.html");//重定向 uri}//  這里用來(lái)配置令牌的訪問(wèn)端點(diǎn)和令牌服務(wù)。@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,這里配置好之后,// 會(huì)自動(dòng)調(diào)用 JwtAccessTokenConverter 將 jwt 解析出來(lái),jwt 里邊就// 包含了用戶的基本信息,所以就不用遠(yuǎn)程校驗(yàn) access_token 了。@Overridepublic void configure(ResourceServerSecurityConfigurer resources) throws Exception {//指定資源id stateless配置基于令牌認(rèn)證
//        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 {
//    // 手動(dòng)添加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("微人事項(xiàng)目接口文檔")
//                        .contact(new Contact("javaboy","https://www.yuque.com/findme","2354827879@qq.com"))
//                        .version("v1.0")
//                        .license("Apache2.0")
//                        .build());
//    }
//    //通過(guò) securitySchemes 來(lái)配置全局參數(shù),這里的配置是一個(gè)名為 Authorization 的請(qǐng)求頭(OAuth2 中需要攜帶的請(qǐng)求頭)。
//    private SecurityScheme securitySchemes() {
//        return new ApiKey("Authorization", "Authorization", "header");
//    }
//
//    // 則用來(lái)配置有哪些請(qǐng)求需要攜帶 Token,這里我們配置了所有請(qǐng)求。
//    private SecurityContext securityContexts() {
//        return SecurityContext.builder()
//                .securityReferences(defaultAuth())
//                .forPaths(PathSelectors.any())
//                .build();
//    }
//
//    // 參數(shù)
//    private List<SecurityReference> defaultAuth() {
//        AuthorizationScope authorizationScope = new AuthorizationScope("xxx", "描述信息");
//        AuthorizationScope[] authorizationScopes = new AuthorizationScope[1];
//        authorizationScopes[0] = authorizationScope;
//        return Arrays.asList(new SecurityReference("Authorization", authorizationScopes));
//    }// 可以在頁(yè)面去配置整個(gè)登錄信息@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")};}// 構(gòu)建時(shí)即得配置 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測(cè)試參數(shù)如下 先獲取token,在傳遞token

2.11configure其他配置

@Overrideprotected void configure(HttpSecurity http) throws Exception {http.authorizeRequests()//開啟配置.antMatchers("/admin/**").hasRole("admin")//路徑符合這個(gè)需要admin角色
//                .antMatchers("user/**").hasAnyRole("admin", "user")//路徑符合這個(gè),需要這兩個(gè)的任意一個(gè).antMatchers("/user/**").access("hasAnyRole('user','admin')").anyRequest().authenticated()//其他請(qǐng)求,登錄后就可以訪問(wèn).and().formLogin()//表單登錄.loginProcessingUrl("/doLogin")//處理登錄請(qǐng)求的地址.loginPage("/login")//配置登錄頁(yè)面(實(shí)際上還是一個(gè)請(qǐng)求地址) 前后端分類不存在這種頁(yè)面 這里還是訪問(wèn)的應(yīng)該請(qǐng)求,會(huì)根據(jù)這請(qǐng)求去返回登錄頁(yè)面.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", "用戶名或密碼輸入錯(cuò)誤,登錄失敗!");} else if (e instanceof DisabledException) {map.put("msg", "賬戶被禁用,登錄失敗!");} else if (e instanceof AccountExpiredException) {map.put("msg", "賬戶過(guò)期,登錄失敗!");} else if (e instanceof CredentialsExpiredException) {map.put("msg", "密碼過(guò)期,登錄失敗!");} else {map.put("msg", "登錄失敗!");}out.write(new ObjectMapper().writeValueAsString(map));out.flush();out.close();}}).permitAll().and().logout().logoutUrl("/logout") //配置注銷請(qǐng)求的地址.logoutSuccessHandler(new LogoutSuccessHandler() {//注銷成功后的回調(diào)@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();/*** 權(quán)限不足處理*/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", "權(quán)限不足!");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", "請(qǐng)先登錄!");
//
//                httpServletResponse.getWriter().println(objectMapper.writeValueAsString(failureMap));
//
//            }
//        });
//

總結(jié)

以上是生活随笔為你收集整理的1.spring security简单的demo-适合萌新的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。