zoukankan      html  css  js  c++  java
  • 简单实现Shiro单点登录(自定义Token令牌)

    1. MVC Controller 映射 sso 方法。

    Java代码  收藏代码
    1. /** 
    2.  * 单点登录(如已经登录,则直接跳转) 
    3.  * @param userCode 登录用户编码 
    4.  * @param token 登录令牌,令牌组成:sso密钥+用户名+日期,进行md5加密,举例:  
    5.  *      String secretKey = Global.getConfig("shiro.sso.secretKey"); 
    6.  *      String token = Digests.md5(secretKey + userCode + DateUtils.getDate("yyyyMMdd")); 
    7.  * @param url 登录成功后跳转的url地址。 
    8.  * @param relogin 是否重新登录,需要重新登录传递true 
    9.  * 例如:http://localhost/project/sso/{token}?url=xxx&relogin=true 
    10.  */  
    11. @RequestMapping(value = "sso/{userCode}/{token}")  
    12. public String sso(@PathVariable String userCode, @PathVariable String token,   
    13.         @RequestParam(required=true) String url, String relogin, Model model) {  
    14.     Principal principal = UserUtils.getPrincipal();  
    15.     // 如果已经登录  
    16.     if(principal != null){  
    17.         // 如果设置强制重新登录,则重新登录  
    18.         if (BooleanUtils.toBoolean(relogin)){  
    19.             UserUtils.getSubject().logout();  
    20.         }  
    21.         // 否则,直接跳转到目标页  
    22.         else{  
    23.             return "redirect:" + Encodes.urlDecode2(url);  
    24.         }  
    25.     }  
    26.     // 进行单点登录  
    27.     if (token != null){  
    28.         UsernamePasswordToken upt = new UsernamePasswordToken();  
    29.         try {  
    30.             upt.setUsername(userCode); // 登录用户名  
    31.             upt.setPassword(token.toCharArray()); // 密码组成:sso密钥+用户名+日期,进行md5加密,举例: Digests.md5(secretKey+username+20150101))  
    32.             upt.setParams(upt.toString()); // 单点登录识别参数,see: AuthorizingRealm.assertCredentialsMatch  
    33.         } catch (Exception ex){  
    34.             if (!ex.getMessage().startsWith("msg:")){  
    35.                 ex = new AuthenticationException("msg:授权令牌错误,请联系管理员。");  
    36.             }  
    37.             model.addAttribute("exception", ex);  
    38.         }  
    39.         try {  
    40.             UserUtils.getSubject().login(upt);  
    41.             return "redirect:" + Encodes.urlDecode2(url);  
    42.         } catch (AuthenticationException ae) {  
    43.             if (!ae.getMessage().startsWith("msg:")){  
    44.                 ae = new AuthenticationException("msg:授权错误,请检查用户配置,若不能解决,请联系管理员。");  
    45.             }  
    46.             model.addAttribute("exception", ae);  
    47.         }  
    48.     }  
    49.     return "error/403";  
    50. }  

     

    2. 重载org.apache.shiro.realm.AuthorizingRealm类的assertCredentialsMatch方法

    Java代码  收藏代码
    1. /** 
    2.  * 认证密码匹配调用方法 
    3.  */  
    4. @Override  
    5. protected void assertCredentialsMatch(AuthenticationToken authcToken,  
    6.         AuthenticationInfo info) throws AuthenticationException {  
    7.     UsernamePasswordToken token = (UsernamePasswordToken) authcToken;  
    8.     // 若单点登录,则使用单点登录授权方法。  
    9.     if (token.toString().equals(token.getParams())){  
    10.         // sso密钥+用户名+日期,进行md5加密,举例: Digests.md5(secretKey+username+20150101))  
    11.         String secretKey = Global.getConfig("shiro.sso.secretKey");  
    12.         String password = Digests.md5(secretKey + token.getUsername() + DateUtils.getDate("yyyyMMdd"));  
    13.         if (password.equals(String.valueOf(token.getPassword()))){  
    14.             return;  
    15.         }  
    16.     }  
    17.     super.assertCredentialsMatch(token, info);  
    18. }  

     

    3. 实现Shiro无状态访问,如通过传递sessionid参数即可实现会话访问

     这里需要自定义Shiro的SessionManager类,方法是继承org.apache.shiro.web.session.mgt.DefaultWebSessionManager类,重载getSessionId方法,如下:

     

    Java代码  收藏代码
    1. public class SessionManager extends DefaultWebSessionManager {  
    2.   
    3.     public SessionManager() {  
    4.         super();  
    5.     }  
    6.       
    7.     @Override  
    8.     protected Serializable getSessionId(ServletRequest request, ServletResponse response) {  
    9.         // 如果参数中包含“__sid”参数,则使用此sid会话。 例如:http://localhost/project?__sid=xxx&__cookie=true  
    10.         // 其实这里还可以使用如下参数:cookie中的session名称:如:JSESSIONID=xxx,路径中的 ;JESSIONID=xxx,但建议还是使用 __sid参数。  
    11.         String sid = request.getParameter("__sid");  
    12.         if (StringUtils.isNotBlank(sid)) {  
    13.             // 是否将sid保存到cookie,浏览器模式下使用此参数。  
    14.             if (WebUtils.isTrue(request, "__cookie")){  
    15.                 HttpServletRequest rq = (HttpServletRequest)request;  
    16.                 HttpServletResponse rs = (HttpServletResponse)response;  
    17.                 Cookie template = getSessionIdCookie();  
    18.                 Cookie cookie = new SimpleCookie(template);  
    19.                 cookie.setValue(sid); cookie.saveTo(rq, rs);  
    20.             }  
    21.             // 设置当前session状态  
    22.             request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_SOURCE,  
    23.                     ShiroHttpServletRequest.URL_SESSION_ID_SOURCE); // session来源与url  
    24.             request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID, sid);  
    25.             request.setAttribute(ShiroHttpServletRequest.REFERENCED_SESSION_ID_IS_VALID, Boolean.TRUE);  
    26.             return sid;  
    27.         }else{  
    28.             return super.getSessionId(request, response);  
    29.         }  
    30.     }  
    31.    
    32. }  
  • 相关阅读:
    MySQL分区性能初探
    FastDFS开源的轻量级分布式文件系统
    MySQL数据类型之数值类型,对理解类型定义中的“位”有莫大的帮助
    空密码引发共享打印机拒绝访问
    利用Myxls导出并下载Excel
    StyleCop SA0102
    Spring AOP介绍
    大学英语一下重修听力考试范围.doc 听力原文 及MP3
    Eclipse中文版
    飞鱼秀下载
  • 原文地址:https://www.cnblogs.com/hzcya1995/p/13317689.html
Copyright © 2011-2022 走看看