{"id":15166,"date":"2013-07-06T15:00:56","date_gmt":"2013-07-06T12:00:56","guid":{"rendered":"http:\/\/www.javacodegeeks.com\/?p=15166"},"modified":"2013-07-05T12:43:15","modified_gmt":"2013-07-05T09:43:15","slug":"su-and-sudo-in-spring-security-applications","status":"publish","type":"post","link":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html","title":{"rendered":"su and sudo in Spring Security applications"},"content":{"rendered":"<p>Long time ago I worked on a project that had a quite powerful feature. There were two roles: user and supervisor. Supervisor could change any document in the system in any way while users were much more limited to workflow constraints. When a normal user had some issue with the document currently being edited and stored in HTTP session, supervisor could step in, switch to special <i>supervisor<\/i> mode and bypass all constrains. Total freedom. Same computer, same keyboard, same HTTP session. Only special flag that supervisor could set by entering secret password. Once the supervisor was done, he or she could clear that flag and enable usual constraints again.<\/p>\n<p>This feature worked well but it was poorly implemented. Availability of every single input field was dependent on that <i>supervisor mode<\/i> flag. Business methods were polluted in dozens of places with <code>isSupervisorMode()<\/code> check. And remember that if supervisor simply logged in using normal credentials, this mode was sort of implicit so security constraints were basically duplicated.<\/p>\n<p>Another interesting use case arises when our application is highly customizable with plenty of security roles. Sooner or later you will face anomaly (OK, <i>bug<\/i>) that you simply can\u2019t reproduce having different privileges. Being able to log in as that particular user and look around might be a big win. Of course you don\u2019t know the passwords of your users (<a href=\"http:\/\/en.wikipedia.org\/wiki\/Cryptographic_hash_function#Password_verification\"><i>don\u2019t you?<\/i><\/a>). UNIX-like systems found solution to this problem: <a href=\"http:\/\/en.wikipedia.org\/wiki\/Su_%28Unix%29\"><code>su<\/code><\/a> (<i>switch user<\/i>) and <a href=\"http:\/\/en.wikipedia.org\/wiki\/Sudo\"><code>sudo<\/code><\/a> commands. Surprisingly <a href=\"http:\/\/static.springsource.org\/spring-security\/site\/index.html\">Spring Security<\/a> ships with built-in <a href=\"http:\/\/static.springsource.org\/spring-security\/site\/docs\/current\/apidocs\/org\/springframework\/security\/web\/authentication\/switchuser\/SwitchUserFilter.html\"><code>SwitchUserFilter<\/code><\/a> that in principle mimics <code>su<\/code> in web applications. Let\u2019s give it a try!<\/p>\n<p>All you need is declaring custom filter:<\/p>\n<pre class=\"brush:xml\">&lt;bean id=\"switchUserProcessingFilter\"\r\n       class=\"org.springframework.security.web.authentication.switchuser.SwitchUserFilter\"&gt;\r\n    &lt;property name=\"userDetailsService\" ref=\"userDetailsService\"\/&gt;\r\n    &lt;property name=\"targetUrl\" value=\"\/\"\/&gt;\r\n&lt;\/b:bean&gt;<\/pre>\n<p>and pointing to it in <code>&lt;http&gt;<\/code> configuration:<\/p>\n<pre class=\"brush:java\">&lt;http auto-config=\"true\" use-expressions=\"true\"&gt;\r\n    &lt;custom-filter position=\"SWITCH_USER_FILTER\" ref=\"switchUserProcessingFilter\" \/&gt;\r\n    &lt;intercept-url pattern=\"\/j_spring_security_switch_user\" access=\"hasRole('ROLE_SUPERVISOR')\"\/&gt;\r\n    ...<\/pre>\n<p>That\u2019s it! Notice that I secure <code>\/j_spring_security_switch_user<\/code> URL pattern. You guessed it, that\u2019s how you log in as a different user, thus we want this resource to be well protected. By default <code>j_username<\/code> parameter name is used. After applying changes above to your web application and logging in with a user having <code>ROLE_SUPERVISOR<\/code> one can simply browse to:<\/p>\n<pre class=\"brush:java\">\/j_spring_security_switch_user?j_username=bob<\/pre>\n<p>And automagically you become logged in as <code>bob<\/code> &#8211; assuming there exists such a user. No password required here. When you are done impersonating him, browsing to <code>\/j_spring_security_exit_user<\/code> will restore your previous credentials. Of course all these URLs are configurable. <code>SwitchUserFilter<\/code> is not documented in <a href=\"http:\/\/static.springsource.org\/spring-security\/site\/docs\/current\/reference\/springsecurity.html\"><i>Reference Documentation<\/i><\/a> but it is a very useful tool when used with caution.<div style=\"display:inline-block; margin: 15px 0;\"> <div id=\"adngin-JavaCodeGeeks_incontent_video-0\" style=\"display:inline-block;\"><\/div> <\/div><\/p>\n<p>Indeed <i>with great power\u2026<\/i>. Giving even most trusted user ability to log in as any other arbitrary user sounds quite risky. Imagine such a feature on Facebook, impossible! ( <a href=\"http:\/\/therumpus.net\/2010\/01\/conversations-about-the-internet-5-anonymous-facebook-employee\/?all=1\">well\u2026<\/a>) Thus tracking and auditing becomes a major requirement.<\/p>\n<p>What I typically do in the first place is adding a small servlet filter right after Spring Security filter that adds user name to <a href=\"http:\/\/logback.qos.ch\/manual\/mdc.html\">MDC<\/a>:<\/p>\n<pre class=\"brush:java\">import org.slf4j.MDC;\r\n \r\npublic class UserNameFilter implements Filter {\r\n \r\n    @Override\r\n    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException {\r\n        final Authentication authentication = SecurityContextHolder.getContext().getAuthentication();\r\n        final String userName = authentication.getName();\r\n        final String fullName = userName + (realName != null ? \" (\" + realName + \")\" : \"\");\r\n \r\n        MDC.put(\"user\", fullName);\r\n        try {\r\n            chain.doFilter(request, response);\r\n        } finally {\r\n            MDC.remove(\"user\");\r\n        }\r\n    }\r\n \r\n    private String findSwitchedUser(Authentication authentication) {\r\n        for (GrantedAuthority auth : authentication.getAuthorities()) {\r\n            if (auth instanceof SwitchUserGrantedAuthority) {\r\n                return ((SwitchUserGrantedAuthority)auth).getSource().getName();\r\n            }\r\n        }\r\n        return null;\r\n    }\r\n \r\n    \/\/...\r\n}<\/pre>\n<p>Just remember to add it to <code>web.xml<\/code> <b>after<\/b> Spring Security. At this point you can reference <code>\"user\"<\/code> key e.g. in <code>logback.xml<\/code>:<\/p>\n<pre class=\"brush:java\">&lt;pattern&gt;%d{HH:mm:ss.SSS} | %-5level | %X{user} | %thread | %logger{1} | %m%n%rEx&lt;\/pattern&gt;<\/pre>\n<p>See the <code>%X{user}<\/code> snippet? Every time logged in user does something in the system that triggers log statement, you will see that users\u2019 name:<\/p>\n<pre class=\"brush:java\">21:56:55.074 | DEBUG | alice | http-bio-8080-exec-9 | ...\r\n\/\/...\r\n21:56:57.314 | DEBUG | bob (alice) | http-bio-8080-exec-3 | ...<\/pre>\n<p>The second log statement is interesting. If you look at <code>findSwitchedUser()<\/code> call above it becomes obvious that <code>alice<\/code>, being a supervisor, switched to user <code>bob<\/code> and now browses on behalf of him.<\/p>\n<p>Sometimes you need even stronger auditing system. Luckily Spring framework has built-in event infrastructure and we can take advantage of <a href=\"http:\/\/static.springsource.org\/spring-security\/site\/docs\/current\/apidocs\/org\/springframework\/security\/web\/authentication\/switchuser\/AuthenticationSwitchUserEvent.html\"><code>AuthenticationSwitchUserEvent<\/code><\/a> sent both when someone switches user and exits this mode:<\/p>\n<pre class=\"brush:java\">@Service\r\npublic class SwitchUserListener\r\n       implements ApplicationListener&lt;AuthenticationSwitchUserEvent&gt; {\r\n \r\n    private static final Logger log = LoggerFactory.getLogger(SwitchUserListener.class);\r\n \r\n    @Override\r\n    public void onApplicationEvent(AuthenticationSwitchUserEvent event) {\r\n        log.info(\"User switch from {} to {}\",\r\n                event.getAuthentication().getName(),\r\n                event.getTargetUser().getUsername());\r\n    }\r\n}<\/pre>\n<p>Of course you can replace simple logging with any business logic you desire, e.g. storing such event in database or sending an e-mail to security officer.<\/p>\n<p>So we know how to log in as a different user for a period of time and then exit such mode. But what if we need \u201c<code>sudo<\/code>\u201d, that is making just one HTTP request on behalf of some other user? Of course we can switch to that user, run that request and then exit. But that seems too heavyweight and cumbersome. Such a requirement may pop up when client program accesses our API and wants to see data as another user (think about testing complex ACLs).<\/p>\n<p>Adding custom HTTP header to denote such a special impersonating request sounds reasonable. It works only for the duration of one request, assuming the client is already authenticating, e.g. using JSESSIONID cookie. Unfortunately this is not supported by Spring Security, but easy to implement on top of <code>SwitchUserFilter<\/code>:<\/p>\n<pre class=\"brush:java\">public class SwitchUserOnceFilter extends SwitchUserFilter {\r\n \r\n    @Override\r\n    public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {\r\n        HttpServletRequest request = (HttpServletRequest) req;\r\n \r\n        final String switchUserHeader = request.getHeader(\"X-Switch-User-Once\");\r\n        if (switchUserHeader != null) {\r\n            trySwitchingUserForThisRequest(chain, request, res, switchUserHeader);\r\n        } else {\r\n            super.doFilter(req, res, chain);\r\n        }\r\n    }\r\n \r\n    private void trySwitchingUserForThisRequest(FilterChain chain, HttpServletRequest request, ServletResponse response, String switchUserHeader) throws IOException, ServletException {\r\n        try {\r\n            proceedWithSwitchedUser(chain, request, response, switchUserHeader);\r\n        } catch (AuthenticationException e) {\r\n            throw Throwables.propagate(e);\r\n        }\r\n    }\r\n \r\n    private void proceedWithSwitchedUser(FilterChain chain, HttpServletRequest request, ServletResponse response, String switchUserHeader) throws IOException, ServletException {\r\n        final Authentication targetUser = attemptSwitchUser(new SwitchUserRequest(request, switchUserHeader));\r\n        SecurityContextHolder.getContext().setAuthentication(targetUser);\r\n \r\n        try {\r\n            chain.doFilter(request, response);\r\n        } finally {\r\n            final Authentication originalUser = attemptExitUser(request);\r\n            SecurityContextHolder.getContext().setAuthentication(originalUser);\r\n        }\r\n \r\n    }\r\n \r\n}<\/pre>\n<p>The only difference from original <code>SwitchUserFilter<\/code> is that if <code>\"X-Switch-User-Once\"<\/code> is present, we switch credentials to user denoted by the value of this header &#8211; however only for the duration of one HTTP request.<code>SwitchUserFilter<\/code> assumes user name to switch to is under <code>j_username<\/code> parameter so I had to cheat a bit with <code>SwitchUserRequest<\/code> wrapper:<\/p>\n<pre class=\"brush:java\">private class SwitchUserRequest extends HttpServletRequestWrapper {\r\n \r\n    private final String switchUserHeader;\r\n \r\n    public SwitchUserRequest(HttpServletRequest request, String switchUserHeader) {\r\n        super(request);\r\n        this.switchUserHeader = switchUserHeader;\r\n    }\r\n \r\n    @Override\r\n    public String getParameter(String name) {\r\n        switch (name) {\r\n            case SPRING_SECURITY_SWITCH_USERNAME_KEY:\r\n                return switchUserHeader;\r\n            default:\r\n                return super.getParameter(name);\r\n        }\r\n    }\r\n}<\/pre>\n<p>And our custom \u201c<code>sudo<\/code>\u201d is in place! You can test it e.g. using <code>curl<\/code>:<\/p>\n<pre class=\"brush:java\">$ curl localhost:8080\/books\/rest\/book \\\r\n    -H \"X-Switch-User-Once: bob\" \\\r\n    -b \"JSESSIONID=...\"<\/pre>\n<p>Of course without <code>JSESSIONID<\/code> cookie the system would not let us in. We have to be logged in first and have special privileges to access <code>sudo<\/code> functionality. Switching user is a handy and quite powerful tool. If you want to try it in practice, check out <a href=\"https:\/\/github.com\/nurkiewicz\/books\">working example on GitHub<\/a>.<br \/>\n&nbsp;<\/p>\n<div style=\"border: 1px solid #D8D8D8; background: #FAFAFA; width: 100%; padding-left: 5px;\"><b><i>Reference: <\/i><\/b><a href=\"http:\/\/nurkiewicz.blogspot.com\/2013\/06\/su-and-sudo-in-spring-security.html\">su and sudo in Spring Security applications<\/a> from our <a href=\"http:\/\/www.javacodegeeks.com\/jcg\">JCG partner<\/a> Tomasz Nurkiewicz at the <a href=\"http:\/\/nurkiewicz.blogspot.com\/\">Java and neighbourhood<\/a> blog.<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Long time ago I worked on a project that had a quite powerful feature. There were two roles: user and supervisor. Supervisor could change any document in the system in any way while users were much more limited to workflow constraints. When a normal user had some issue with the document currently being edited and &hellip;<\/p>\n","protected":false},"author":13,"featured_media":240,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[8],"tags":[30,125],"class_list":["post-15166","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-enterprise-java","tag-spring","tag-spring-security"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.5 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>su and sudo in Spring Security applications<\/title>\n<meta name=\"description\" content=\"Long time ago I worked on a project that had a quite powerful feature. There were two roles: user and supervisor. Supervisor could change any document in\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"su and sudo in Spring Security applications\" \/>\n<meta property=\"og:description\" content=\"Long time ago I worked on a project that had a quite powerful feature. There were two roles: user and supervisor. Supervisor could change any document in\" \/>\n<meta property=\"og:url\" content=\"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html\" \/>\n<meta property=\"og:site_name\" content=\"Java Code Geeks\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/www.facebook.com\/javacodegeeks\" \/>\n<meta property=\"article:published_time\" content=\"2013-07-06T12:00:56+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"150\" \/>\n\t<meta property=\"og:image:height\" content=\"150\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Tomasz Nurkiewicz\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@https:\/\/twitter.com\/tnurkiewicz\" \/>\n<meta name=\"twitter:site\" content=\"@javacodegeeks\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Tomasz Nurkiewicz\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"6 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/su-and-sudo-in-spring-security-applications.html#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/su-and-sudo-in-spring-security-applications.html\"},\"author\":{\"name\":\"Tomasz Nurkiewicz\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/fb1be85725c10e8361e641fa851e79e1\"},\"headline\":\"su and sudo in Spring Security applications\",\"datePublished\":\"2013-07-06T12:00:56+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/su-and-sudo-in-spring-security-applications.html\"},\"wordCount\":846,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/su-and-sudo-in-spring-security-applications.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"keywords\":[\"Spring\",\"Spring Security\"],\"articleSection\":[\"Enterprise Java\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/su-and-sudo-in-spring-security-applications.html#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/su-and-sudo-in-spring-security-applications.html\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/su-and-sudo-in-spring-security-applications.html\",\"name\":\"su and sudo in Spring Security applications\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/su-and-sudo-in-spring-security-applications.html#primaryimage\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/su-and-sudo-in-spring-security-applications.html#primaryimage\"},\"thumbnailUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"datePublished\":\"2013-07-06T12:00:56+00:00\",\"description\":\"Long time ago I worked on a project that had a quite powerful feature. There were two roles: user and supervisor. Supervisor could change any document in\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/su-and-sudo-in-spring-security-applications.html#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/su-and-sudo-in-spring-security-applications.html\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/su-and-sudo-in-spring-security-applications.html#primaryimage\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2012\\\/10\\\/spring-logo.jpg\",\"width\":150,\"height\":150,\"caption\":\"spring-interview-questions-answers\"},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/2013\\\/07\\\/su-and-sudo-in-spring-security-applications.html#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\"},{\"@type\":\"ListItem\",\"position\":3,\"name\":\"Enterprise Java\",\"item\":\"https:\\\/\\\/www.javacodegeeks.com\\\/category\\\/java\\\/enterprise-java\"},{\"@type\":\"ListItem\",\"position\":4,\"name\":\"su and sudo in Spring Security applications\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#website\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"name\":\"Java Code Geeks\",\"description\":\"Java Developers Resource Center\",\"publisher\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\"},\"alternateName\":\"JCG\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/www.javacodegeeks.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Organization\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#organization\",\"name\":\"Exelixis Media P.C.\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/\",\"logo\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\",\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"contentUrl\":\"https:\\\/\\\/www.javacodegeeks.com\\\/wp-content\\\/uploads\\\/2022\\\/06\\\/exelixis-logo.png\",\"width\":864,\"height\":246,\"caption\":\"Exelixis Media P.C.\"},\"image\":{\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/logo\\\/image\\\/\"},\"sameAs\":[\"https:\\\/\\\/www.facebook.com\\\/javacodegeeks\",\"https:\\\/\\\/x.com\\\/javacodegeeks\"]},{\"@type\":\"Person\",\"@id\":\"https:\\\/\\\/www.javacodegeeks.com\\\/#\\\/schema\\\/person\\\/fb1be85725c10e8361e641fa851e79e1\",\"name\":\"Tomasz Nurkiewicz\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f2a8f9f1060fc7c1161c42f8ba901e0e79fb767dec39ec34b2d3b95cab9dc728?s=96&d=mm&r=g\",\"url\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f2a8f9f1060fc7c1161c42f8ba901e0e79fb767dec39ec34b2d3b95cab9dc728?s=96&d=mm&r=g\",\"contentUrl\":\"https:\\\/\\\/secure.gravatar.com\\\/avatar\\\/f2a8f9f1060fc7c1161c42f8ba901e0e79fb767dec39ec34b2d3b95cab9dc728?s=96&d=mm&r=g\",\"caption\":\"Tomasz Nurkiewicz\"},\"description\":\"Java EE developer, Scala enthusiast. Enjoying data analysis and visualization. Strongly believes in the power of testing and automation.\",\"sameAs\":[\"http:\\\/\\\/nurkiewicz.blogspot.com\\\/\",\"https:\\\/\\\/x.com\\\/https:\\\/\\\/twitter.com\\\/tnurkiewicz\"],\"url\":\"https:\\\/\\\/www.javacodegeeks.com\\\/author\\\/tomasz-nurkiewicz\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"su and sudo in Spring Security applications","description":"Long time ago I worked on a project that had a quite powerful feature. There were two roles: user and supervisor. Supervisor could change any document in","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html","og_locale":"en_US","og_type":"article","og_title":"su and sudo in Spring Security applications","og_description":"Long time ago I worked on a project that had a quite powerful feature. There were two roles: user and supervisor. Supervisor could change any document in","og_url":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html","og_site_name":"Java Code Geeks","article_publisher":"https:\/\/www.facebook.com\/javacodegeeks","article_published_time":"2013-07-06T12:00:56+00:00","og_image":[{"width":150,"height":150,"url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","type":"image\/jpeg"}],"author":"Tomasz Nurkiewicz","twitter_card":"summary_large_image","twitter_creator":"@https:\/\/twitter.com\/tnurkiewicz","twitter_site":"@javacodegeeks","twitter_misc":{"Written by":"Tomasz Nurkiewicz","Est. reading time":"6 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html#article","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html"},"author":{"name":"Tomasz Nurkiewicz","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/fb1be85725c10e8361e641fa851e79e1"},"headline":"su and sudo in Spring Security applications","datePublished":"2013-07-06T12:00:56+00:00","mainEntityOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html"},"wordCount":846,"commentCount":0,"publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","keywords":["Spring","Spring Security"],"articleSection":["Enterprise Java"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html#respond"]}]},{"@type":"WebPage","@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html","url":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html","name":"su and sudo in Spring Security applications","isPartOf":{"@id":"https:\/\/www.javacodegeeks.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html#primaryimage"},"image":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html#primaryimage"},"thumbnailUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","datePublished":"2013-07-06T12:00:56+00:00","description":"Long time ago I worked on a project that had a quite powerful feature. There were two roles: user and supervisor. Supervisor could change any document in","breadcrumb":{"@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html#primaryimage","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2012\/10\/spring-logo.jpg","width":150,"height":150,"caption":"spring-interview-questions-answers"},{"@type":"BreadcrumbList","@id":"https:\/\/www.javacodegeeks.com\/2013\/07\/su-and-sudo-in-spring-security-applications.html#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/www.javacodegeeks.com\/"},{"@type":"ListItem","position":2,"name":"Java","item":"https:\/\/www.javacodegeeks.com\/category\/java"},{"@type":"ListItem","position":3,"name":"Enterprise Java","item":"https:\/\/www.javacodegeeks.com\/category\/java\/enterprise-java"},{"@type":"ListItem","position":4,"name":"su and sudo in Spring Security applications"}]},{"@type":"WebSite","@id":"https:\/\/www.javacodegeeks.com\/#website","url":"https:\/\/www.javacodegeeks.com\/","name":"Java Code Geeks","description":"Java Developers Resource Center","publisher":{"@id":"https:\/\/www.javacodegeeks.com\/#organization"},"alternateName":"JCG","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/www.javacodegeeks.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Organization","@id":"https:\/\/www.javacodegeeks.com\/#organization","name":"Exelixis Media P.C.","url":"https:\/\/www.javacodegeeks.com\/","logo":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/","url":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","contentUrl":"https:\/\/www.javacodegeeks.com\/wp-content\/uploads\/2022\/06\/exelixis-logo.png","width":864,"height":246,"caption":"Exelixis Media P.C."},"image":{"@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/logo\/image\/"},"sameAs":["https:\/\/www.facebook.com\/javacodegeeks","https:\/\/x.com\/javacodegeeks"]},{"@type":"Person","@id":"https:\/\/www.javacodegeeks.com\/#\/schema\/person\/fb1be85725c10e8361e641fa851e79e1","name":"Tomasz Nurkiewicz","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/secure.gravatar.com\/avatar\/f2a8f9f1060fc7c1161c42f8ba901e0e79fb767dec39ec34b2d3b95cab9dc728?s=96&d=mm&r=g","url":"https:\/\/secure.gravatar.com\/avatar\/f2a8f9f1060fc7c1161c42f8ba901e0e79fb767dec39ec34b2d3b95cab9dc728?s=96&d=mm&r=g","contentUrl":"https:\/\/secure.gravatar.com\/avatar\/f2a8f9f1060fc7c1161c42f8ba901e0e79fb767dec39ec34b2d3b95cab9dc728?s=96&d=mm&r=g","caption":"Tomasz Nurkiewicz"},"description":"Java EE developer, Scala enthusiast. Enjoying data analysis and visualization. Strongly believes in the power of testing and automation.","sameAs":["http:\/\/nurkiewicz.blogspot.com\/","https:\/\/x.com\/https:\/\/twitter.com\/tnurkiewicz"],"url":"https:\/\/www.javacodegeeks.com\/author\/tomasz-nurkiewicz"}]}},"_links":{"self":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/15166","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/users\/13"}],"replies":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/comments?post=15166"}],"version-history":[{"count":0,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/posts\/15166\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media\/240"}],"wp:attachment":[{"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/media?parent=15166"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/categories?post=15166"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.javacodegeeks.com\/wp-json\/wp\/v2\/tags?post=15166"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}