忘了愛

导航

Spring security

Spring security解決方法是
添加校验token
由于CSRF的本质在于攻击者欺骗用户去访问自己设置的地址,所以如果要求在访问敏感数据请求时,要求用户浏览器提供不保存在cookie中,并且攻击者无法伪造的数据作为校验,那么攻击者就无法再运行CSRF攻击。这种数据通常是窗体中的一个数据项。服务器将其生成并附加在窗体中,其内容是一个伪随机数。当客户端通过窗体提交请求时,这个伪随机数也一并提交上去以供校验。正常的访问时,客户端浏览器能够正确得到并传回这个伪随机数,而通过CSRF传来的欺骗性攻击中,攻击者无从事先得知这个伪随机数的值,服务端就会因为校验token的值为空或者错误,拒绝这个可疑请求

開啟csrf
有csrf用隱藏域

關閉csrf
則沒有_csrf隱藏域

@RestController
public class HelloController {

    //只有dba能訪問
    @GetMapping("/db/hello")
    public String DBHello(){return "db hello";}
    //只有admin能訪問
    @GetMapping("/admin/hello")
    public String adminHello(){return "admin hello";}
    //只有user能訪問
    @GetMapping("/user/hello")
    public String userHello(){return "user hello";}
    //任何人都能訪問
    @GetMapping("/hello")
    public String Hello(){return "hello world";}
}

如果硬加上ROLE_

public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Bean
    PasswordEncoder passwordEncoder(){
        return NoOpPasswordEncoder.getInstance();
    }

    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        /**
         * 配置三個用戶
         * root 具備ADMIN DBA
         * admin 具備 ADMIN USER
         * sang USER
         */
        auth.inMemoryAuthentication()
                .withUser("root").password("123").roles("ADMIN","DBA")
                .and()
                .withUser("admin").password("123").roles("ADMIN","USER")
                .and()
                .withUser("sang").password("123").roles("USER");

    }

   @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                // /hello任何人都可訪問
                .antMatchers("/hello").permitAll()
                //.hasRole會自動加上ROLE_ 所以腳色名稱必須為ROLE_db
                //只有admin
                .antMatchers("/db/**").hasRole("db").anyRequest().authenticated()
                //只有dba
                .antMatchers("/admin/**").hasRole("admin").anyRequest().authenticated()
                //只有user
                .antMatchers("/user/**").hasRole("user").anyRequest().authenticated()
                .and()
                //登入接口任何人都能訪問
                .formLogin().loginProcessingUrl("/login").permitAll()
                .successHandler(new AuthenticationSuccessHandler() {
                    @Override
                    public void onAuthenticationSuccess(HttpServletRequest req,
                                                        HttpServletResponse resp,
                                                        Authentication auth)
                            throws IOException {
                        Object principal = auth.getPrincipal();
                        resp.setContentType("application/json;charset=utf-8");
                        PrintWriter out = resp.getWriter();
                        resp.setStatus(200);
                        Map<String, Object> map = new HashMap<>();
                        map.put("status", 200);
                        map.put("msg", principal);
                        ObjectMapper om = new ObjectMapper();
                        out.write(om.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .failureHandler(new AuthenticationFailureHandler() {

                    @Override
                    public void onAuthenticationFailure(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, AuthenticationException e) throws IOException, ServletException {
                        httpServletResponse.setContentType("application/json;charset=utf-8");
                        PrintWriter out = httpServletResponse.getWriter();
                        httpServletResponse.setStatus(401);
                        Map<String, Object> map = new HashMap<>();
                        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", "登入失敗");
                        }
                        ObjectMapper om = new ObjectMapper();
                        out.write(om.writeValueAsString(map));
                        out.flush();
                        out.close();
                    }
                })
                .and()
                .csrf()
                .disable();

    }

}

持久化保存用戶與腳色

public class User implements UserDetails {
    private  Integer id;
    private String username;
    private String password;
    private Boolean enabled;
    private Boolean locked;
}
@Component
public class UserService implements UserDetailsService {
    @Autowired
    UserMapper userMapper;
    @Autowired
    RoleMapper roleMapper;


    @Override
    public UserDetails loadUserByUsername(String s) throws UsernameNotFoundException {
        User user = userMapper.findByName(s);
        if(user == null)
            throw new UsernameNotFoundException("找不到帳戶");
        user.setRoles(roleMapper.findById(user.getId()));
        System.out.println(user);
        return user;
    }
}

public class MyWebSecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(AuthenticationManagerBuilder auth) throws Exception {
        auth.userDetailsService(userService);
    }
}
.........



測試
導入依賴
```xml
<dependency>
      <groupId>org.springframework.security</groupId>
      <artifactId>spring-security-test</artifactId>
      <scope>test</scope>
</dependency>
@RunWith(SpringRunner.class)
@SpringBootTest
class DemoApplicationTests {
    @Autowired
    UserMapper userMapper;
    @Autowired
    UserService userService;
        @Autowired
    RoleMapper roleMapper;
        @Autowired
    WebApplicationContext wac;
    MockMvc mockMvc;


    @Test
    @WithMockUser(value = "miku" ,password = "1")
    public void helloControllerTest() throws Exception {
        mockMvc = MockMvcBuilders.webAppContextSetup(wac).build();
        MvcResult mvcResult = mockMvc.perform(
                MockMvcRequestBuilders
                .get("/db/hello"))
//                .get("/hello"))
                .andExpect(MockMvcResultMatchers.status().isOk())
                .andDo(MockMvcResultHandlers.print())
                .andReturn();
        System.out.println(mvcResult.getResponse().getContentAsString());
    }
}

posted on 2020-11-27 15:23  忘了愛  阅读(61)  评论(0编辑  收藏  举报