public class StatelessDefaultSubjectFactory extends DefaultWebSubjectFactory { @Override public Subject createSubject(SubjectContext context) { context.setSessionCreationEnabled(false); return super.createSubject(context); } }我们自定义一个无状态的Filter:
public class StatelessAuthcFilter extends AccessControlFilter { @Override protected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception { return false; } @Override protected boolean onAccessDenied(ServletRequest servletRequest, ServletResponse servletResponse) throws Exception { //客户端生成的消息摘要 String clientDigest=servletRequest.getParameter("digest"); //客户端传入的用户身份 String username=servletRequest.getParameter("username"); //客户端的参数列表 String param1=servletRequest.getParameter("param1"); String param2=servletRequest.getParameter("param2"); Map<String,String> params=new HashMap<>(); params.put("param1",param1); params.put("param2",param2); //生成无状态Token StatelessToken token=new StatelessToken(username,params,clientDigest); try { getSubject(servletRequest,servletResponse).login(token); } catch (Exception e) { e.printStackTrace(); onLoginFail(servletResponse); } return false; } private void onLoginFail(ServletResponse response) throws IOException { HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.setStatus(HttpServletResponse.SC_UNAUTHORIZED); httpResponse.getWriter().write("login error"); } }shiro框架没有提供专门的无状态的token,我们自己定义一个:
public class StatelessToken implements AuthenticationToken { private String username; private Map<String, ?> params; private String clientDigest; public StatelessToken(String username, Map<String, ?> params, String clientDigest) { this.username = username; this.params = params; this.clientDigest = clientDigest; }。。。。。此处省略set和get代码自定义无状态的realm:
public class StatelessRealm extends AuthorizingRealm { @Autowired private IMememberService memberService; @Override public boolean supports(AuthenticationToken token) { //仅支持StatelessToken类型的Token return token instanceof StatelessToken; } @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) { String username = (String) principalCollection.getPrimaryPrincipal(); Member user = memberService.findByUsername(username); // System.out.println(user); if (user != null) { SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo(); return authorizationInfo; } else throw new IncorrectCredentialsException(); } @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws AuthenticationException { StatelessToken statelessToken = (StatelessToken) token; String username = statelessToken.getUsername(); String key = getKey(username);//根据用户名获取密钥(和客户端的一样) //在服务器端生成客户端参数消息摘要 String serverDigest = HmacSHA256Utils.digest(key, statelessToken.getParams()); System.out.println(statelessToken.getClientDigest()); System.out.println(serverDigest); //然后进行客户端消息摘要和服务器端消息摘要的匹配 return new SimpleAuthenticationInfo( username, serverDigest, getName()); } /** * 获取秘钥,此处是硬编码的一个 * * @param username * @return */ private String getKey(String username) { if("admin".equals(username)) { return "dadadswdewq2ewdwqdwadsadasd"; } return null; } }然后进行shiro的配置文件部分内容:
<!--statelessReealm--> <bean id="statelessRealm" class="com.supuy.sps.realm.StatelessRealm"> <property name="cachingEnabled" value="false"/> </bean> <!--statelessReealm subject工厂--> <bean id="subjectFactory" class="com.supuy.sps.realm.factory.StatelessDefaultSubjectFactory"></bean> <!--statelessFilter--> <bean id="statelessFilter" class="com.supuy.sps.realm.filter.StatelessAuthcFilter"></bean>
这里的sessionManager的sessionValidationSchedulerEnabled属性一定得设置为false。
这样就可以使用啦。这里没有列出对用户名和消息生成消息摘要的类,基本上就是对属性加密的一个类。
原文地址:http://blog.csdn.net/js_sky/article/details/45765663