> 文章列表 > Solon2 简单的单点登录SSO实现

Solon2 简单的单点登录SSO实现

Solon2 简单的单点登录SSO实现

简单的单点登录,目前可以基于 solon.sessionstate.jwt 插件实现。假定场景是多个管理后台,使用二级域名分别为:

  • a.demo.org
  • b.demo.org
  • c.demo.org

各个管理后台,在一个导航页面上。在导航页面上的链接(“/login”),用户点击后,如果是已登录跳到管理页,未登录显示登录页。

1、简单的流程设计

  • 跳到登录页。如果有发现已登录,而跳到当前用户上次打开的页面;否则显示登录界面
  • 登录页。登录成功后,在 sessin 里登记用户标识
  • 管理页。使用验证插件的登录验证注解。(实战时,用签权框架更合适)

2、方案实现

1)添加配置

#可共享域配置(可不配,默认当前服务域名;多系统共享时要配置)
server.session.state.domain: "demo.org" #用一级域名#Jwt 密钥(使用 JwtUtils.createKey() 生成)
server.session.state.jwt.secret: "E3F9N2kRDQf55pnJPnFoo5+ylKmZQ7AXmWeOVPKbEd8=" 

2)实现登录相关控制

登录与退出控制(jwt 会通过 cookie 传,不用管细节)

@Controller
public class LoginController {//登录@Mapping("/login")public ModelAndView login(Context ctx){if(ctx.sessionAsLong("user_id", 0L) > 0){//跳到管理后台主页(或者打开cookie记住的最近请求页面)ctx.redirect("/admin/main");return null;}else{//显示登录界面return new ModelAndView("/login");}}//登录处理@Mapping("/login/ajax/do")public Result loginAjaxDo(Context ctx, String username, String password){if (username == "test" && password == "1234") {//获取登录的用户idlong userId = 1001;//登录ctx.sessionSet("user_id", userId);return Result.succeed();}else{return Result.failure();}}//退出页@Mapping("logout")public void logout(Context ctx) {ctx.sessionClear();}
}

3)与验证器插件 solon.validation 的登录验证做结合(实战时,用签权框架更合适)

配置登录注解的检测器

@Configuration
public class Config {@Beanpublic LoginedChecker loginedChecker() {return (anno, ctx, userKeyName) -> ctx.sessionAsLong("user_id", 0L) > 0;}
}

再加个登录验证器出错的处理,未登录的自动跳到登录页

//可以和其它异常处理合并一个过滤器
@Component
public class ValidatorFailureFilter implements Filter {@Overridepublic void doFilter(Context ctx, FilterChain chain) throws Throwable {try {chain.doFilter(ctx);} catch (ValidatorException e) {if(e.getAnnotation() instanceof Logined){ctx.redirect("/login"); //如果验证出错的是 Logined 注解,则跳到登录页上}else {ctx.render(Result.failure(e.getCode(), e.getMessage())); }}}
}

4)登录验证注解在管理页的使用

@Logined //可以使用验证注解了
@Mapping("admin")
@Controller
public class AdminController extends BaseController{@Mapping("test")public String test(){return "OK";}
}