多平台统一管理软件接口,如何实现多平台统一管理软件接口
261
2023-02-09
Spring Boot整合Spring Security的示例代码
本文讲述Spring Boot整合Spring Security在方法上使用注解实现权限控制,使用自定义UserDetailService,从mysql中加载用户信息。使用Security自带的MD5加密,对用户密码进行加密。页面模板采用thymeleaf引擎。
源码地址:https://github.com/li5454yong/springboot-security.git
1、引入pom依赖
这里使用druid连接池,Spring Data Jpa实现数据库访问。
2、配置Spring Security
@Configuration
@EnableWebMvcSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)//开启security注解
public class WebSecurityConfig extends WebSecurityConfigurerAdapter {
@Bean
@Override
protected AuthenticationManager authenticationManager() throws Exception {
return super.authenticationManager();
}
@Override
protected void configure(HttpSecurity http) throws Exception {
//允许所有用户访问"/"和"/home"
http.authorizeRequests()
.antMatchers("/", "/home").permitAll()
//其他地址的访问均需验证权限
.anyRequest().authenticated()
.and()
.formLogin()
//指定登录页是"/login"
.loginPage("/login")
.defaultSuccessUrl("/hello")//登录成功后默认跳转到"/hello"
.permitAll()
.and()
.logout()
.logoutSuccessUrl("/home")//退出登录后的默认url是"/home"
.permitAll();
}
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth
.userDetailsService(customUserDetailsService())
.passwordEncoder(passwordEncoder());
}
/**
* 设置用户密码的加密方式为MD5加密
* @return
*/
@Bean
public Md5PasswordEncoder passwordEncoder() {
return new Md5PasswordEncoder();
}
/**
* 自定义UserDetailsService,从数据库中读取用户信息
* @return
*/
@Bean
public CustomUserDetailsService customUserDetailsService(){
return new CustomUserDetailsService();
}
}
这里只做了基本的配置,设置了登录url、登录成功后跳转的url、退出后跳转到的url。使用@EnableGlobalMethodSecurity(prePostEnabled = true)这个注解,可以开启security的注解,我们可以在需要控制权限的方法上面使用@PreAuthorize,@PreFilter这些注解。
3、自定义userDetailService
public class CustomUserDetailsService implements UserDetailsService {
@Autowired //数据库服务类
private SUserService suserService;
@Override
public UserDetails loadUserByUsername(String userName) throws UsernameNotFoundException {
//SUser对应数据库中的用户表,是最终存储用户和密码的表,可自定义
//本例使用SUser中的email作为用户名:
SUser user = suserService.findUserByEmail(userName);
if (user == null) {
throw new UsernameNotFoundException("UserName " + userName + " not found");
}
// SecurityUser实现UserDetails并将SUser的Email映射为username
SecurityUser securityUser = new SecurityUser(user);
Collection
authorities.add(new SimpleGrantedAuthority("ROLE_ADMIN"));
return securityUser;
}
}
这里只需要实现UserDetailsService 接口,重写loadUserByUsername方法,从数据库中取出用户信息。最后返回一个UserDetails 实现类。
4、定义错误处理配置
@Configuration
public class ErrorPageConfig {
@Bean
public EmbeddedServletContainerCustomizer embeddedServletContainerCustomizer(){
return new MyCustomizer();
}
private static class MyCustomizer implements EmbeddedServletContainerCustomizer {
@Override
public void customize(ConfigurableEmbeddedServletContainer container) {
container.addErrorPages(new ErrorPage(HttpStatus.FORBIDDEN, "/403"));
}
}
}
访问发生错误时,跳转到”/403”.
5、Controller接口
@Controller
public class IndexController {
@Resource
private SUserService sUserService;
@RequestMapping("/home")
public String home() {
return "home";
}
@PreAuthorize("hasRole('user')")
@RequestMapping(value = "/admin",method = RequestMethod.GET)
public String toAdmin(){
return "helloAdmin";
}
@RequestMapping("/hello")
public String hello() {
return "hello";
}
@RequestMapping("/login")
public String login(){
return "login";
}
@RequestMapping("/")
public String root() {
return "index";
}
@RequestMapping("/403")
public String error(){
return "403";
}
}
在toAdmin()方法上面使用了@PreAuthorize(“hasRole(‘user')”),表示访问这个方法需要拥有user角色。如果希望控制到权限层面,可以使用@PreAuthorize(“hasPermission()”)。这里只是用了其中的一个用法,更多的使用方法可以去看官方文档。需要注意的是,Spring Security默认的角色前缀是”ROLE_”,使用hasRole方法时已经默认加上了,因此我们在数据库里面的用户角色应该是“ROLE_user”,在user前面加上”ROLE_”前缀。
6、测试
启动项目,访问http://localhost:1130/login
点击登录后进入到“/hello”
点击跳转到管理员页面
在后台的“/admin”这个url对应的方法上面,限制了用户必须要拥有“user”角色。在数据库中也设置了登录的用户有这个角色。
现在我们修改数据库中的用户角色,改为“ROLE_admin”。退出登录后重新登录,再次点击“前往管理员页面”按钮,会跳转到如下页面。
因为现在没有了“user”权限,所以访问的时候抛出了异常,被拦截后重定向到了“/403”。
7、POST方式访问,错误码403
首先,把“/admin”改为POST请求
@PreAuthorize("hasRole('user')")
@RequestMapping(value = "/admin",method = RequestMethod.POST)
public String toAdmin(){
return "helloAdmin";
}
把“前往管理员页面”按钮的请求方式从原来的form表达get提交,改为ajax方式POST提交。至于为什么不是用form的POST提交后面再讲。先修改代码
function testPost() {
$.ajax({
url:"/admin",
type:'POST',
success:function (data) {
}
});
}
点击“前往管理员页面”按钮,在调试台可以看到如下
这是因为框架内部防止CSRF(Cross-site request forgery跨站请求伪造)的发生,限制了除了get以外的大多数方法。
下面说解决办法:
首先在标签内添加如下内容。
只要添加这个token,后台就会验证这个token的正确性,如果正确,则接受post访问。
然后在ajax代码中添加以下代码:
var token = $('meta[name="_csrf"]').attr("content");
var header = $('meta[name="_csrf_hader"]').attr("content");
$(document).ajaxSend(function(e,xhr,opt){
xhr.setRequestHeader(header,token);
});
这样就可以正常使用POST、DELETE等其他方式来访问了。
上面说到使用表单的POST方式来提交,通过查看页面源代码可以看到
框架在form表单中自动插入了一个隐藏域,value值就是那个token,所以使用form表单来提交POST请求是可以直接通过的,而ajax方式提交的话,需要加上那段代码。
好了,这篇文章就讲到这,后面还会有文章讲述REST API风格如何来使用Spring Security来控制权限。
版权声明:本文内容由网络用户投稿,版权归原作者所有,本站不拥有其著作权,亦不承担相应法律责任。如果您发现本站中有涉嫌抄袭或描述失实的内容,请联系我们jiasou666@gmail.com 处理,核实后本网站将在24小时内删除侵权内容。
发表评论
暂时没有评论,来抢沙发吧~