Python 官方文档:入门教程 => 点击学习
目录说明spring Security与shiro的区别简单使用登录校验流程引入Security设置用户名和密码使用配置类过滤规则授权方式WEB授权方法授权顺序优先级登出跨域认证失败
Spring Security是一个功能强大且高度可定制的身份验证和访问控制框架。Spring Security是一个专注于为Java应用程序提供身份验证和授权的框架。与所有Spring项目一样,Spring安全性的真正威力在于它可以很容易地扩展以满足定制需求。
一般Web应用的需要进行认证和授权。
Spring Security 是 Spring家族中的一个安全管理框架。相比与另外一个安全框架Shiro,它提供了更丰富的功能,社区资源也比Shiro丰富。相对于Shiro,在ssh/SSM中整合Spring Security都是比较麻烦的操作,但有了Spring Boot之后,Spring Boot 对于 Spring Security 提供了 自动化配置方案,可以零配置使用 Spring Security。因此,一般来说常见的安全管理技术栈组合是:
在SpringBoot项目中使用SpringSecurity只需要引入依赖即可。
<!-- spring security 安全认证 -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
在application.properties中添加属性:
server.port=8080
#spring.security.user.name=root
#spring.security.user.passWord=123456
#Mysql数据库连接
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.datasource.url=jdbc:mysql://localhost:3306/security?serverTimezone=GMT%2B8
spring.datasource.username=root
spring.datasource.password=123456
但是在application.properties中添加属性意味着登录系统的用户名的密码都是固定的,不推荐。可以使用配置类,在配置类中设置,配置类的优先级更高。
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter
{
@Autowired
private UserDetailsService userDetailsService;
@Autowired
private AuthenticationEntryPointImpl unauthorizedHandler;
@Autowired
private LoGoutSuccessHandlerImpl logoutSuccessHandler;
@Autowired
private JwtAuthenticationTokenFilter authenticationTokenFilter;
@Bean
@Override
public AuthenticationManager authenticationManagerBean() throws Exception
{
return super.authenticationManagerBean();
}
@Override
protected void configure(httpsecurity HttpSecurity) throws Exception
{
httpSecurity
// CRSF禁用,因为不使用session
.csrf().disable()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
// 对于登录login 允许匿名访问
.antMatchers("/login").anonymous()
.antMatchers(
HttpMethod.GET,
"*.html",
"*.CSS",
"/file*.js"
).permitAll()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()
.headers().frameOptions().disable();
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
// 添加JWT filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
}
@Bean
public BCryptPasswordEncoder bCryptPasswordEncoder()
{
return new BCryptPasswordEncoder();
}
@Override
protected void configure(AuthenticationManagerBuilder auth) throws Exception
{
auth.userDetailsService(userDetailsService).passwordEncoder(bCryptPasswordEncoder());
}
}
@Service("ss")
public class PermissionService
{
private static final String ALL_PERMISSION = "*:*:*";
private static final String SUPER_ADMIN = "admin";
private static final String ROLE_DELIMETER = ",";
private static final String PERMISSION_DELIMETER = ",";
@Autowired
private TokenService tokenService;
public boolean hasPermi(String permission)
{
if (StringUtils.isEmpty(permission))
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
{
return false;
}
return hasPermissions(loginUser.getPermissions(), permission);
}
public boolean lacksPermi(String permission)
{
return hasPermi(permission) != true;
}
public boolean hasAnyPermi(String permissions)
{
if (StringUtils.isEmpty(permissions))
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getPermissions()))
{
return false;
}
Set<String> authorities = loginUser.getPermissions();
for (String permission : permissions.split(PERMISSION_DELIMETER))
{
if (permission != null && hasPermissions(authorities, permission))
{
return true;
}
}
return false;
}
public boolean hasRole(String role)
{
if (StringUtils.isEmpty(role))
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
{
return false;
}
for (SysRole sysRole : loginUser.getUser().getRoles())
{
String roleKey = sysRole.getRoleKey();
if (SUPER_ADMIN.contains(roleKey) || roleKey.contains(StringUtils.trim(role)))
{
return true;
}
}
return false;
}
public boolean lacksRole(String role)
{
return hasRole(role) != true;
}
public boolean hasAnyRoles(String roles)
{
if (StringUtils.isEmpty(roles))
{
return false;
}
LoginUser loginUser = tokenService.getLoginUser(ServletUtils.getRequest());
if (StringUtils.isNull(loginUser) || CollectionUtils.isEmpty(loginUser.getUser().getRoles()))
{
return false;
}
for (String role : roles.split(ROLE_DELIMETER))
{
if (hasRole(role))
{
return true;
}
}
return false;
}
private boolean hasPermissions(Set<String> permissions, String permission)
{
return permissions.contains(ALL_PERMISSION) || permissions.contains(StringUtils.trim(permission));
}
}
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/list")
public TableDataInfo list(SysUser user)
{
startPage();
List<SysUser> list = userService.selectUserList(user);
return getDataTable(list);
}
创建一个Service文件用于Security查询用户信息:
@Service
public class UserDetailsServiceImpl implements UserDetailsService
{
private static final Logger log = LoggerFactory.getLogger(UserDetailsServiceImpl.class);
@Autowired
private ISysUserService userService;
@Autowired
private SysPermissionService permissionService;
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException
{
// 根据账户号查询用户信息
SysUser user = userService.selectUserByUserName(username);
if (StringUtils.isNull(user))
{
log.info("登录用户:{} 不存在.", username);
throw new UsernameNotFoundException("登录用户:" + username + " 不存在");
}
else if (UserStatus.DELETED.getCode().equals(user.getDelFlag()))
{
log.info("登录用户:{} 已被删除.", username);
throw new BaseException("对不起,您的账号:" + username + " 已被删除");
}
else if (UserStatus.DISABLE.getCode().equals(user.getStatus()))
{
log.info("登录用户:{} 已被停用.", username);
throw new BaseException("对不起,您的账号:" + username + " 已停用");
}
return createLoginUser(user);
}
public UserDetails createLoginUser(SysUser user)
{
// 获取用户权限
return new LoginUser(user, permissionService.getMenuPermission(user));
}
}
当用户请求时,Security便会拦截请求,取出其中的username字段,从Service中查询该账户,并将信息填充到一个userDetails对象中返回。这样Security便拿到了填充后的userDetails对象,也就是获取到了包括权限在内的用户信息。
WebSecurityConfigurerAdapter.configure(HttpSecurity http)
Security的授权方式有两种:
@Override
httpSecurity.authorizeRequests() // 对请求进行授权
.antMatchers("/test1").hasAuthority("p1") // 设置/test1接口需要p1权限
.antMatchers("/test2").hasAnyRole("admin", "manager") // 设置/test2接口需要admin或manager角色
.and()
.headers().frameOptions().disable();
其中:
同理:
@PreAuthorize("@ss.hasPermi('system:user:list')")
@GetMapping("/list")
public TableDataInfo list(SysUser user)
{
startPage();
List<SysUser> list = userService.selectUserList(user);
return getDataTable(list);
}
校验是按照配置的顺序从上往下进行。若某个条件已匹配过,则后续同条件的匹配将不再被执行。也就是说,若多条规则是相互矛盾的,则只有第一条规则生效。典型地:
// 只有具有权限a的用户才能访问/get/resource
httpSecurity.authorizeRequests()
.antMatchers("/get/resource").hasAuthority("a")
.anyRequest().permitAll();
// 所有用户都能访问/get/resource
httpSecurity.authorizeRequests()
.anyRequest().permitAll()
.antMatchers("/get/resource").hasAuthority("a");
但若是包含关系,则需要将细粒度的规则放在前面:
// /get/resource需要权限a,除此之外所有的/get
@Configuration
public class LogoutSuccessHandlerImpl implements LogoutSuccessHandler
{
@Autowired
private TokenService tokenService;
@Override
public void onLogoutSuccess(HttpServletRequest request, HttpServletResponse response, Authentication authentication)
throws IOException, ServletException
{
LoginUser loginUser = tokenService.getLoginUser(request);
if (StringUtils.isNotNull(loginUser))
{
String userName = loginUser.getUsername();
// 删除用户缓存记录
tokenService.delLoginUser(loginUser.getToken());
}
ServletUtils.renderString(response, JSON.toJSONString(ajaxResult.error(HttpStatus.SUCCESS, "退出成功")));
}
}
httpSecurity.cors()
.and()
.csrf().disable();
cors()允许跨域资源访问。
csrf().disable()禁用跨域安全验证。
@Component
public class AuthenticationEntryPointImpl implements AuthenticationEntryPoint, Serializable
{
private static final long serialVersionUID = -8970718410437077606L;
@Override
public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException e)
throws IOException
{
int code = HttpStatus.UNAUTHORIZED;
String msg = StringUtils.fORMat("请求访问:{},认证失败,无法访问系统资源", request.getRequestURI());
ServletUtils.renderString(response, JSON.toJSONString(AjaxResult.error(code, msg)));
}
}
到此这篇关于Spring Security实现基于角色的访问控制框架的文章就介绍到这了,更多相关Spring Security访问控制框架内容请搜索编程网以前的文章或继续浏览下面的相关文章希望大家以后多多支持编程网!
--结束END--
本文标题: SpringSecurity实现基于角色的访问控制框架
本文链接: https://lsjlt.com/news/210890.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-03-01
2024-03-01
2024-03-01
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0