jeyson的专栏

shiro的无状态web集成。所谓无状态就是服务器端无状态,就是不保存会话。一般的会话机制的web应用,都是session机制来保存用户状态。无状态的web应用就是每次请求都带上相应的用户名进行登录。 具体的实践就是:客户端传入秘钥和一个消息作为输入,他们声称相应消息摘要,秘钥是只有客户端和服务端知道的。访问的时候服务端对消息摘要进行验证。 具体的实例如下: 首先我们创建subject的工厂必须是不保存session的: public class StatelessDefaultSubjectFactory extends DefaultWebSubjectFactory {@Overridepublic Subject createSubject(SubjectContext context){context.setSessionCreationEnabled(false);return super.createSubject(context);}} 我们自定义一个无状态的Filter:public class StatelessAuthcFilter extends AccessControlFilter {@Overrideprotected boolean isAccessAllowed(ServletRequest servletRequest, ServletResponse servletResponse, Object o) throws Exception {return false;}@Overrideprotected 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);//生成无状态TokenStatelessToken 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 {@Autowiredprivate IMememberService memberService;@Overridepublic boolean supports(AuthenticationToken token) {//仅支持StatelessToken类型的Tokenreturn token instanceof StatelessToken;}@Overrideprotected 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();}@Overrideprotected 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>

这样就可以使用啦。这里没有列出对用户名和消息生成消息摘要的类,基本上就是对属性加密的一个类。

人只要不失去方向,就不会失去自己

jeyson的专栏

相关文章:

你感兴趣的文章:

标签云: