目录标题
- 1.授权认证
- 1.1 定义
- 1.2.实现
- 1.2.1 授权登录接口
- 1.2.2 授权回调接口
- 1.2.3 过滤器链
- 1.2.3 过滤器配置
- 2.权限管理
- 2.1 接口权限
- 2.2 菜单权限
1.授权认证
1.1 定义
这里是通过spring security实现了 SSO单点登录认证
具体步骤就是:
1.客户端 收到了登录请求(“/login”),带上回调地址等信息,直接跳转至 第三方登陆页面
2.用户在 第三方登陆页面 输入账户、密码
3.第三方登陆页面 访问 客户端 给的回调地址(传参包括 授权码)
4.客户端 根据授权码等信息,调用 第三方登录系统 获取令牌的接口,获取Token
5.客户端将Token添加到cookie中,并返回给前端
之后前端的每次操作都会带上Token,而客户端也会解析Token,从而获取用户的信息,并把用户信息更新到SecurityContext (安全上下文)中。
1.2.实现
1.2.1 授权登录接口
@ReqestMapping("/login")
public String login(HttpServletRequest request ,HttpServletResponse response){
//拼接第三方登录接口的url:url本身 + param
//param包括项目信息、指定返回url......
//这里用到了springboot快捷的重定向方式(返回后会自动帮我们重定向到url去)
return "redirect:url";
}
1.2.2 授权回调接口
@ReqestMapping("/login-callback")
public String login(HttpServletRequest request ,HttpServletResponse response,String state ,String code , String returnUri){
//校验state (不接这个参数也可以,用的话也是用来防止CSRF攻击的)
//将授权码等作为param,调取 第三方获取Token的接口,获取Token,将Token放到cookie中,然后返回给前端
//这里用到了springboot快捷的重定向方式(返回后会自动帮我们重定向到指定的url中)
return "redirect:"+ returnUri;
}
1.2.3 过滤器链
既然是用了 spring security 技术,那肯定是涉及到 过滤器链了。下面举例:
这里的FIlter顺序为:ExceptionHandlerFilter–> Filter1 —>…
//用于捕获过滤器链在执行中产生的异常,所以要放在最前面
//这里用的过滤器和平常见到的大同小异
@Component
public class ExceptionHandlerFilter exetends OncePerRequestFilter {
@override
public void doFilterInternal(HttpServletRequest request , HttpServletResponse response ,FilterChain filterChain) {
try{
filterChain.dochain(request,response);
}catch(Exception e){
//异常处理
}
}
}
// 获取用户信息
public class Filter1 exetends OncePerRequestFilter {
@override
public void doFilterInternal(HttpServletRequest request , HttpServletResponse response ,FilterChain filterChain) {
//从header或cookie中拿取Token
//解析Token,获取用户信息
//用户信息保存到SecurityContext(安全上下文中)
filterChain.dochain(request,response);
}
}
1.2.3 过滤器配置
通过spring security的 WebSecurityConfigurerAdapter配置过滤器链
@Configuration
@EnableWebSecurity
public class SecurityConfig extends WebSecurityConfigurerAdapter {
@Resource
private Filter1 filter1;
@Resource
private ExceptionHandlerFilter exceptionHandlerFilter;
static {
// 允许子线程拿到父线程的鉴权信息
SecurityContextHolder.setStrategyName(SecurityContextHolder.MODE_INHERITABLETHREADLOCAL);
}
@Override
protected void configure(HttpSecurity http) throws Exception {
ExpressionUrlAuthorizationConfigurer<HttpSecurity>.ExpressionInterceptUrlRegistry registry = http.authorizeRequests();
registry.anyRequest().authenticated();
//关闭跨域请求验证
registry.and().csrf().disable();
//添加过滤器
registry.and()
.addFilterBefore(filter2, UsernamePasswordAuthenticationFilter.class)
.addFilterBefore(exceptionHandlerFilter, CorsFilter.class);
}
}
2.权限管理
权限管理的最好方式就是给用户们,设置几个不同的角色,根据角色来确定用户的权限。
而我们所指的权限一般指两种:接口、菜单
2.1 接口权限
创建一张角色和接口的关系表
role | auth |
admin | [GET]/me |
admin | [GET]/list |
admin | [POST]/buy |
user | [GET]/me |
temp_user | [GET]/me |
由上表可以看出,管理员admin拥有3个接口的权限,而user、temp_user只有1个接口的权限。
至于如何编写提供项目所有接口的代码,可以自行百度。
2.2 菜单权限
创建一张角色和菜单的关系表
role | menu |
admin | goods |
admin | orders |
admin | news |
user | goods |
temp_user | goods |
由上表可以看出,管理员admin拥有3个菜单的权限,而user、temp_user只有goods菜单的权限。
我们只需要给前端提供这些信息,剩余操作由前端完成。