在springboot中集成spring security,实现不同角色的权限控制,有以下几个问题,希望帮忙解答一下,感激不尽,很久都没有解决。
问题1:登录处理url报403错误(因为权限问题无法访问),按照之前提过的问题,将http.csrf().disable()之后,登录url是可以访问了,但我不想这样做。有什么办法吗?
问题2:自定义UserDetailService中的loadUserByUsername,没有获取到前台的值(前台传的参数是account和pwd),如果改成参数改成username和pwd,就可以获取到前台的值。
问题3:真正的登录验证函数没有被执行到(没有返回相应数据),只执行了loadUserByUsername,没有执行@RequestMapping("login")映射的方法。
我不知道是不是我的思路有问题,是不是在spring security中,执行了loadUserByUsername,就不会执行自己的验证函数了?:@RequestMapping("login"),感觉应该不是这样。
以下是spring boot集成security的主要代码(也是在网上参考的资料):
主要参考:http://blog.csdn.net/u0127025...
WebSecurity
@Configuration
@EnableWebSecurity
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
UserDetailsService customUserService() { //注册UserDetailsService 的bean
return new CustomUserService();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
http.headers().frameOptions().disable().and() //允许嵌入iframe
.csrf().disable()
.authorizeRequests()
.antMatchers("/css/**", "/js/**","/images/**", "**/favicon.ico", "/lib/**").permitAll()
.antMatchers("/admin/**").hasRole(SysConfig.ROLE_ADMIN)
.anyRequest().authenticated().and()
//.rememberMe().tokenValiditySeconds(60 * 60 * 24 * 7).key("").and()
.formLogin().loginProcessingUrl("/user/login").loginPage("/login.html").permitAll().and()
.logout().permitAll();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception {
auth.userDetailsService(customUserService());
}
}
CustomUserService
@Service
public class CustomUserService implements UserDetailsService {
@Autowired
private UserService userService;
@Override
public UserDetails loadUserByUsername(String account) throws UsernameNotFoundException {
System.out.println("loadUser " + account);
User user = userService.getUserByAccount(account);
if (user == null || user.isHasDel()) {
throw new UsernameNotFoundException("user not exist or has been deleted");
}
List<GrantedAuthority> auths = new ArrayList<>();
for (Role role : user.getRoles()) {
auths.add(new SimpleGrantedAuthority(role.getName())); //不同用户会返回不同的role.name:USER, ADMIN
}
return new org.springframework.security.core.userdetails.User(account, user.getPwd(), auths);
}
}
UserController中的login
@PostMapping("login")
public TMessage login(String account, String pwd) {
if (StringUtil.isEmpty(account) || StringUtil.isEmpty(pwd) || !account.contains("@"))
return new TMessage(TMessage.CODE_FAILURE, "用户名密码为空或格式不正确");
if (userService.login(account, pwd))
return new TMessage(TMessage.CODE_SUCCESS, "登录成功");
else
return new TMessage(TMessage.CODE_FAILURE, "登录失败,请检查用户名和密码");
}
如果前台是这样的格式
username: a@b,
pwd: aaabbb
customservice中才能接收到username,其他参数接受不到,我想指定参数名是account,并且进入自己的处理函数(根据用户名和密码)
问题一:
默认Spring Security对CSRF攻击进行了防范,该项配置默认为开的状态,它会在页面到服务端请求过程中通过一个token来进行请求安全校验,如果前端使用jsp来渲染,那么需要在表单增加一个隐藏域来解决:
如果使用thymeleaf2.1+模板或者使用了
Spring MVC <form:form>
标签,那么CsrfToken
这个值会被自动加入进去如果你使用的是ajax json请求,这时候就不能使用Http Paramaters来传入这个token,这时候 你可以通过head来提交这个token,代码如下:
基于jquery的demo:
问题二:
Spring Security允许我们进行自定义校验,即实现
UserDetailService
接口,无论你使用任何类型的数据库存储或者调用第三方接口,那么你需要做的是就是将其返回结果进行转换成Spring Security.User所需要的东西,在做转换的时候,我们可能会想到的是使用apache commons-beanutils
做数据转换(只是帮助思考,底层不一定是用它来实现),所以在使用的时候,你想使用参数名accout
转换成spring security
的username,这个只能要我们自己手动来转换了,因为即使Spring Security再智能,他也是按照一定的约定来进行转换,所以你转换失败也是正常的...