spring-security实现角色权限的控制

spring-security实现角色权限的控制

spring-security提供了方便的权限控制方法,我们只需进行简单的配置就可以实现而不再需要使用「硬代码」的方式来进行编写。

这样开发人员就可以专注于业务逻辑的编写。

访问url按照用户角色进行授权

请先访问我以前写的前后端分离的实现spring-security实现前后端分离登录

在以上的基础上再进行授权的访问分配。

@Configuration
@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

	private PasswordEncoder myPasswordEncoder;

	private CustomUserService myCustomUserService;

	private ObjectMapper objectMapper;

	public SecurityConfig(CustomUserService myCustomUserService, ObjectMapper objectMapper) {
		this.myPasswordEncoder =new BCryptPasswordEncoder();
		this.myCustomUserService = myCustomUserService;
		this.objectMapper = objectMapper;
	}

	@Override
	protected void configure(HttpSecurity http) throws Exception {

		http
				.authenticationProvider(authenticationProvider())
				.httpBasic()
				//未登录时,进行json格式的提示,很喜欢这种写法,不用单独写一个又一个的类
				.authenticationEntryPoint((request,response,authException) -> {
					response.setContentType("application/json;charset=utf-8");
					response.setStatus(HttpServletResponse.SC_FORBIDDEN);
					PrintWriter out = response.getWriter();
					Map<String,Object> map = new HashMap<String,Object>();
					map.put("code",403);
					map.put("message","未登录");
					out.write(objectMapper.writeValueAsString(map));
					out.flush();
					out.close();
				})

				.and()
				.authorizeRequests()
				// user访问下的所有url,只有ADMIN才能够进行访问
				.antMatchers("/user/**").hasRole("ADMIN")
				.anyRequest().authenticated() //必须授权才能范围

				.and()
				.formLogin() //使用自带的登录
				.permitAll()
				//登录失败,返回json
				.failureHandler((request,response,ex) -> {
					response.setContentType("application/json;charset=utf-8");
					response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
					PrintWriter out = response.getWriter();
					Map<String,Object> map = new HashMap<String,Object>();
					map.put("code",401);
					if (ex instanceof UsernameNotFoundException || ex instanceof BadCredentialsException) {
						map.put("message","用户名或密码错误");
					} else if (ex instanceof DisabledException) {
						map.put("message","账户被禁用");
					} else {
						map.put("message","登录失败!");
					}
					out.write(objectMapper.writeValueAsString(map));
					out.flush();
					out.close();
				})
				//登录成功,返回json
				.successHandler((request,response,authentication) -> {
					Map<String,Object> map = new HashMap<String,Object>();
					map.put("code",200);
					map.put("message","登录成功");
					map.put("data",authentication);
					response.setContentType("application/json;charset=utf-8");
					PrintWriter out = response.getWriter();
					out.write(objectMapper.writeValueAsString(map));
					out.flush();
					out.close();
				})
				.and()
				.exceptionHandling()
				//没有权限,返回json
				.accessDeniedHandler((request,response,ex) -> {
					response.setContentType("application/json;charset=utf-8");
					response.setStatus(HttpServletResponse.SC_FORBIDDEN);
					PrintWriter out = response.getWriter();
					Map<String,Object> map = new HashMap<String,Object>();
					map.put("code",403);
					map.put("message", "权限不足");
					out.write(objectMapper.writeValueAsString(map));
					out.flush();
					out.close();
				})
				.and()
				.logout()
				//退出成功,返回json
				.logoutSuccessHandler((request,response,authentication) -> {
					Map<String,Object> map = new HashMap<String,Object>();
					map.put("code",200);
					map.put("message","退出成功");
					map.put("data",authentication);
					response.setContentType("application/json;charset=utf-8");
					PrintWriter out = response.getWriter();
					out.write(objectMapper.writeValueAsString(map));
					out.flush();
					out.close();
				})
				.permitAll();
		//开启跨域访问
		http.cors().disable();
		//开启模拟请求,比如API POST测试工具的测试,不开启时,API POST为报403错误
		http.csrf().disable();
	}

	@Override
	public void configure(WebSecurity web) {
		//对于在header里面增加token等类似情况,放行所有OPTIONS请求。
		web.ignoring().antMatchers(HttpMethod.OPTIONS, "/**");
	}

	@Bean
	public AuthenticationProvider authenticationProvider() {
		DaoAuthenticationProvider authenticationProvider = new DaoAuthenticationProvider();
		//对默认的UserDetailsService进行覆盖
		authenticationProvider.setUserDetailsService(myCustomUserService);
		authenticationProvider.setPasswordEncoder(myPasswordEncoder);
		return authenticationProvider;
	}

}

根据用户的角色进行判断是否有权限进行访问

创建role实体类,并且实现GrantedAuthority接口

public class RolePo implements GrantedAuthority {
		// 这里为了方便进行测试,所以写成了固定的角色
    private String role="ROLE_ADMIN";
    @Override
    public String getAuthority() {
        return this.getRole();
    }

    public String getRole() {
        return role;
    }

    public void setRole(String role) {
        this.role = role;
    }
}

User实体类实现UserDetail接口,并重写getAuthorities方法。

public class SysUserPo implements UserDetails {

    @TableId(type = IdType.AUTO)
    private Integer id;

    @TableField(value  ="user_name")
    private String userName;

    @TableField(value = "password")
    private String password;

    @TableField(value = "role")
    private String role;

    @Override
    public Collection<? extends GrantedAuthority> getAuthorities() {
        List<GrantedAuthority> auths = new ArrayList<>();
        RolePo role=new RolePo();
        auths.add(role);
        return auths;
    }

    @Override
    public String getUsername() {
        System.out.println(this.userName);
        return this.userName;
    }

    @Override
    public boolean isAccountNonExpired() {
        return true;
    }

    @Override
    public boolean isAccountNonLocked() {
        return true;
    }

    @Override
    public boolean isCredentialsNonExpired() {
        return true;
    }

    @Override
    public boolean isEnabled() {
        return true;
    }

}

进行测试

@RequestMapping("/user")
@RestController
public class UserController {
    @GetMapping("/get")
    public String getUser(){
        return "bulingfeng";
    }
}

访问http://127.0.0.1:8080/user/get。能够访问到数据。

修改role中的默认值,比如修改成ROLE_USER。再次启动并且访问,返回403 forbiden。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值