| 1 | import org.codehaus.groovy.grails.plugins.springsecurity.RedirectUtils |
|---|
| 2 | import org.grails.plugins.springsecurity.service.AuthenticateService |
|---|
| 3 | |
|---|
| 4 | import org.springframework.security.AuthenticationTrustResolverImpl |
|---|
| 5 | import org.springframework.security.DisabledException |
|---|
| 6 | import org.springframework.security.context.SecurityContextHolder as SCH |
|---|
| 7 | import org.springframework.security.ui.AbstractProcessingFilter |
|---|
| 8 | import org.springframework.security.ui.webapp.AuthenticationProcessingFilter |
|---|
| 9 | |
|---|
| 10 | /** |
|---|
| 11 | * Login Controller (Example). |
|---|
| 12 | */ |
|---|
| 13 | class LoginController { |
|---|
| 14 | |
|---|
| 15 | /** |
|---|
| 16 | * Dependency injection for the authentication service. |
|---|
| 17 | */ |
|---|
| 18 | def authenticateService |
|---|
| 19 | |
|---|
| 20 | /** |
|---|
| 21 | * Dependency injection for OpenIDConsumer. |
|---|
| 22 | */ |
|---|
| 23 | def openIDConsumer |
|---|
| 24 | |
|---|
| 25 | /** |
|---|
| 26 | * Dependency injection for OpenIDAuthenticationProcessingFilter. |
|---|
| 27 | */ |
|---|
| 28 | def openIDAuthenticationProcessingFilter |
|---|
| 29 | |
|---|
| 30 | private final authenticationTrustResolver = new AuthenticationTrustResolverImpl() |
|---|
| 31 | |
|---|
| 32 | def index = { |
|---|
| 33 | if (isLoggedIn()) { |
|---|
| 34 | redirect uri: '/' |
|---|
| 35 | } |
|---|
| 36 | else { |
|---|
| 37 | redirect action: auth, params: params |
|---|
| 38 | } |
|---|
| 39 | } |
|---|
| 40 | |
|---|
| 41 | def loggedOut = { |
|---|
| 42 | flash['message'] = 'Successfully logged out' |
|---|
| 43 | auth() |
|---|
| 44 | } |
|---|
| 45 | |
|---|
| 46 | /** |
|---|
| 47 | * Show the login page. |
|---|
| 48 | */ |
|---|
| 49 | def auth = { |
|---|
| 50 | |
|---|
| 51 | nocache(response) |
|---|
| 52 | |
|---|
| 53 | if (isLoggedIn()) { |
|---|
| 54 | redirect uri: '/' |
|---|
| 55 | return |
|---|
| 56 | } |
|---|
| 57 | |
|---|
| 58 | String view |
|---|
| 59 | String postUrl |
|---|
| 60 | def config = authenticateService.securityConfig.security |
|---|
| 61 | if (config.useOpenId) { |
|---|
| 62 | view = 'openIdAuth' |
|---|
| 63 | postUrl = "${request.contextPath}/login/openIdAuthenticate" |
|---|
| 64 | } |
|---|
| 65 | else if (config.useFacebook) { |
|---|
| 66 | view = 'facebookAuth' |
|---|
| 67 | postUrl = "${request.contextPath}${config.facebook.filterProcessesUrl}" |
|---|
| 68 | } |
|---|
| 69 | else { |
|---|
| 70 | view = 'auth' |
|---|
| 71 | postUrl = "${request.contextPath}${config.filterProcessesUrl}" |
|---|
| 72 | } |
|---|
| 73 | |
|---|
| 74 | render view: view, model: [postUrl: postUrl] |
|---|
| 75 | } |
|---|
| 76 | |
|---|
| 77 | /** |
|---|
| 78 | * Form submit action to start an OpenID authentication. |
|---|
| 79 | */ |
|---|
| 80 | def openIdAuthenticate = { |
|---|
| 81 | String openID = params['j_username'] |
|---|
| 82 | try { |
|---|
| 83 | String returnToURL = RedirectUtils.buildRedirectUrl( |
|---|
| 84 | request, response, openIDAuthenticationProcessingFilter.filterProcessesUrl) |
|---|
| 85 | String redirectUrl = openIDConsumer.beginConsumption(request, openID, returnToURL) |
|---|
| 86 | redirect url: redirectUrl |
|---|
| 87 | } |
|---|
| 88 | catch (org.springframework.security.ui.openid.OpenIDConsumerException e) { |
|---|
| 89 | log.error "Consumer error: $e.message", e |
|---|
| 90 | redirect url: openIDAuthenticationProcessingFilter.authenticationFailureUrl |
|---|
| 91 | } |
|---|
| 92 | } |
|---|
| 93 | |
|---|
| 94 | // Login page (function|json) for Ajax access. |
|---|
| 95 | def authAjax = { |
|---|
| 96 | nocache(response) |
|---|
| 97 | //this is example: |
|---|
| 98 | render """ |
|---|
| 99 | <script type='text/javascript'> |
|---|
| 100 | (function() { |
|---|
| 101 | loginForm(); |
|---|
| 102 | })(); |
|---|
| 103 | </script> |
|---|
| 104 | """ |
|---|
| 105 | } |
|---|
| 106 | |
|---|
| 107 | /** |
|---|
| 108 | * The Ajax success redirect url. |
|---|
| 109 | */ |
|---|
| 110 | def ajaxSuccess = { |
|---|
| 111 | nocache(response) |
|---|
| 112 | render '{success: true}' |
|---|
| 113 | } |
|---|
| 114 | |
|---|
| 115 | /** |
|---|
| 116 | * Show denied page. |
|---|
| 117 | */ |
|---|
| 118 | def denied = { |
|---|
| 119 | if (isLoggedIn() && authenticationTrustResolver.isRememberMe(SCH.context?.authentication)) { |
|---|
| 120 | // have cookie but the page is guarded with IS_AUTHENTICATED_FULLY |
|---|
| 121 | redirect action: full, params: params |
|---|
| 122 | } |
|---|
| 123 | } |
|---|
| 124 | |
|---|
| 125 | /** |
|---|
| 126 | * Login page for users with a remember-me cookie but accessing a IS_AUTHENTICATED_FULLY page. |
|---|
| 127 | */ |
|---|
| 128 | def full = { |
|---|
| 129 | render view: 'auth', params: params, |
|---|
| 130 | model: [hasCookie: authenticationTrustResolver.isRememberMe(SCH.context?.authentication)] |
|---|
| 131 | } |
|---|
| 132 | |
|---|
| 133 | // Denial page (data|view|json) for Ajax access. |
|---|
| 134 | def deniedAjax = { |
|---|
| 135 | //this is example: |
|---|
| 136 | render "{error: 'access denied'}" |
|---|
| 137 | } |
|---|
| 138 | |
|---|
| 139 | /** |
|---|
| 140 | * login failed |
|---|
| 141 | */ |
|---|
| 142 | def authfail = { |
|---|
| 143 | |
|---|
| 144 | def username = session[AuthenticationProcessingFilter.SPRING_SECURITY_LAST_USERNAME_KEY] |
|---|
| 145 | def msg = '' |
|---|
| 146 | def person = Person.findByLoginName(username) |
|---|
| 147 | def exception = session[AbstractProcessingFilter.SPRING_SECURITY_LAST_EXCEPTION_KEY] |
|---|
| 148 | if (exception) { |
|---|
| 149 | if (exception instanceof DisabledException) { |
|---|
| 150 | msg = "[$username] is disabled." |
|---|
| 151 | } |
|---|
| 152 | else if (person?.authorities?.isEmpty()) { |
|---|
| 153 | msg = "[$username] has no granted authority." |
|---|
| 154 | } |
|---|
| 155 | else { |
|---|
| 156 | msg = "[$username] wrong username/password." |
|---|
| 157 | } |
|---|
| 158 | } |
|---|
| 159 | |
|---|
| 160 | if (isAjax()) { |
|---|
| 161 | render "{error: '${msg}'}" |
|---|
| 162 | } |
|---|
| 163 | else { |
|---|
| 164 | flash.message = msg |
|---|
| 165 | redirect action: auth, params: params |
|---|
| 166 | } |
|---|
| 167 | } |
|---|
| 168 | |
|---|
| 169 | /** |
|---|
| 170 | * Check if logged in. |
|---|
| 171 | */ |
|---|
| 172 | private boolean isLoggedIn() { |
|---|
| 173 | return authenticateService.isLoggedIn() |
|---|
| 174 | } |
|---|
| 175 | |
|---|
| 176 | private boolean isAjax() { |
|---|
| 177 | return authenticateService.isAjax(request) |
|---|
| 178 | } |
|---|
| 179 | |
|---|
| 180 | /** cache controls */ |
|---|
| 181 | private void nocache(response) { |
|---|
| 182 | response.setHeader('Cache-Control', 'no-cache') // HTTP 1.1 |
|---|
| 183 | response.addDateHeader('Expires', 0) |
|---|
| 184 | response.setDateHeader('max-age', 0) |
|---|
| 185 | response.setIntHeader ('Expires', -1) //prevents caching at the proxy server |
|---|
| 186 | response.addHeader('cache-Control', 'private') //IE5.x only |
|---|
| 187 | } |
|---|
| 188 | } |
|---|