Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to use Spring Boot+Shiro to realize privilege Management

2025-01-18 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/02 Report--

This article mainly introduces how to use Spring Boot+Shiro to achieve rights management, the article is very detailed, has a certain reference value, interested friends must read it!

One: configure the pom.xml file

Org.apache.shiro shiro-spring 1.4.0

Two: ShiroConfig configuration class

@ Configurationpublic class ShiroConfig {@ Bean ("sessionManager") public SessionManager sessionManager () {DefaultWebSessionManager sessionManager = new DefaultWebSessionManager (); sessionManager.setGlobalSessionTimeout (24 * 60 * 60 * 1000); / / Open session verifier sessionManager.setSessionValidationSchedulerEnabled (true); / / Delete invalid session sessionManager.setDeleteInvalidSessions (true) / / specify sessionId and use the default "JSESSIONID" sessionManager.setSessionIdCookieEnabled (true); return sessionManager;} / * when we use shiro, we will initialize SecurityManager first, and then inject other components of shiro, such as sessionManager, realm, into SecurityManager. * / @ Bean ("securityManager") public SecurityManager securityManager (OAuth3Realm oAuth3Realm, SessionManager sessionManager) {DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager (); securityManager.setRealm (oAuth3Realm); securityManager.setSessionManager (sessionManager); return securityManager;} @ Bean ("shiroFilter") public ShiroFilterFactoryBean shirFilter (SecurityManager securityManager) {ShiroFilterFactoryBean shiroFilter = new ShiroFilterFactoryBean () ShiroFilter.setSecurityManager (securityManager); / / oauth filtering Map filters = new HashMap (); filters.put ("oauth3", new OAuth3Filter ()); shiroFilter.setFilters (filters) / / configure addresses that can be accessed anonymously. You can add and release some static resources according to the actual situation. Anon means to release Map filterMap = new LinkedHashMap (); filterMap.put ("/ webjars/**", "anon"); filterMap.put ("/ druid/**", "anon") FilterMap.put ("/ app/**", "anon"); filterMap.put ("/ file/**", "anon"); filterMap.put ("/ shiro/login", "anon"); filterMap.put ("/ swagger/**", "anon"); filterMap.put ("/ v2/api-docs", "anon") FilterMap.put ("/ swagger-ui.html", "anon"); filterMap.put ("/ swagger-resources/**", "anon"); filterMap.put ("/ captcha.jpg", "anon"); / / other filtering filterMap.put through custom OAuth3Filter ("/ *", "oauth3") ShiroFilter.setFilterChainDefinitionMap (filterMap); return shiroFilter;} @ Bean ("lifecycleBeanPostProcessor") public LifecycleBeanPostProcessor lifecycleBeanPostProcessor () {return new LifecycleBeanPostProcessor () } / * * @ Title: defaultAdvisorAutoProxyCreator * @ Description: scan the context, look for all Advistor (notifiers), apply these Advisor to a bean of * @ return Spring in all the Bean that match the pointcut, and it is up to Advisor to decide which classes of methods are AOP proxies. * @ return DefaultAdvisorAutoProxyCreator return type * @ throws * / @ Bean// public DefaultAdvisorAutoProxyCreator defaultAdvisorAutoProxyCreator () {/ / DefaultAdvisorAutoProxyCreator proxyCreator = new DefaultAdvisorAutoProxyCreator (); / / proxyCreator.setProxyTargetClass (true); / / return proxyCreator / /} / * * @ Title: authorizationAttributeSourceAdvisor * @ Description: enable shiro aop annotation to support * @ param securityManager * @ return parameters description * @ return AuthorizationAttributeSourceAdvisor return type * @ throws * / @ Bean public AuthorizationAttributeSourceAdvisor authorizationAttributeSourceAdvisor (SecurityManager securityManager) { AuthorizationAttributeSourceAdvisor advisor = new AuthorizationAttributeSourceAdvisor () Advisor.setSecurityManager (securityManager); return advisor;}}

Among them, if DefaultAdvisorAutoProxyCreator is enabled, it will cause the problem of secondary proxy, and the doGetAuthorizationInfo in Realm will be called twice.

Three: custom Shiro Filter class OAuth3Filter

Public class OAuth3Filter extends AuthenticatingFilter {@ Override protected AuthenticationToken createToken (ServletRequest request, ServletResponse response) throws Exception {/ / get request token String token = getRequestToken ((HttpServletRequest) request); if (StringUtils.isNullOrEmpty (token)) {return null;} return new OAuth3Token (token) } @ Override protected boolean isAccessAllowed (ServletRequest request, ServletResponse response, Object mappedValue) {/ / now axios is used in vue projects to send http requests. Each request will have one more RequestMethod: OPTIONS request, called "pre-check" request if (HttpServletRequest) request). GetMethod () .equals (RequestMethod.OPTIONS.name () {return true;} return false } @ Override protected boolean onAccessDenied (ServletRequest request, ServletResponse response) throws Exception {/ / get request token. If token does not exist, directly return 401 String token = getRequestToken ((HttpServletRequest) request); if (StringUtils.isNullOrEmpty (token)) {HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.setHeader ("Access-Control-Allow-Credentials", "true") HttpResponse.setHeader ("Access-Control-Allow-Origin", HttpContextUtils.getOrigin ()); String json = new Gson (). ToJson (R.error (HttpStatus.SC_UNAUTHORIZED, "invalid token")); httpResponse.getWriter (). Print (json); return false;} return executeLogin (request, response) } @ Override protected boolean onLoginFailure (AuthenticationToken token, AuthenticationException e, ServletRequest request, ServletResponse response) {HttpServletResponse httpResponse = (HttpServletResponse) response; httpResponse.setContentType ("application/json;charset=utf-8"); httpResponse.setHeader ("Access-Control-Allow-Credentials", "true"); httpResponse.setHeader ("Access-Control-Allow-Origin", HttpContextUtils.getOrigin ()) Try {/ / handles the exception of login failure Throwable throwable = e.getCause () = null? E: e.getCause (); R r = R.error (HttpStatus.SC_UNAUTHORIZED, throwable.getMessage ()); String json = new Gson (). ToJson (r); httpResponse.getWriter (). Print (json);} catch (IOException E1) {} return false } / * get the requested token * / private String getRequestToken (HttpServletRequest httpRequest) {/ / get token String token = httpRequest.getHeader ("token") from header; / / if token does not exist in header, get token if (StringUtils.isNullOrEmpty (token)) {token = httpRequest.getParameter ("token") from the parameter;} return "112233445566"; / / token }}

For complex cross-domain requests, Vue first sends an OPTIONS request for verification. The backend needs to uniformly handle and release the OPTIONS method for all interfaces (that is, return 200).

Four: custom Token

Public class OAuth3Token implements AuthenticationToken {private String token; public OAuth3Token (String token) {this.token = token;} / * * login submitted user name * * / @ Override public String getPrincipal () {return token } / * * secret values that are only known by Subject, such as the password provided by our login * * / @ Override public Object getCredentials () {return token;}}

Five: custom OAuth3Realm

@ Componentpublic class OAuth3Realm extends AuthorizingRealm {@ Autowired private ShiroService shiroService; / * * determine whether this Realm supports this Token * / @ Override public boolean supports (AuthenticationToken token) {return token instanceof OAuth3Token } / * * provide user information and return permission information * * / @ Override protected AuthorizationInfo doGetAuthorizationInfo (PrincipalCollection principals) {System.out.println ("= get logged-in user, permission information ="); SysUserEntity user = (SysUserEntity) principals.getPrimaryPrincipal () Long userId = user.getUserId (); / / user rights list Set permsSet = shiroService.getUserPermissions (userId); SimpleAuthorizationInfo info = new SimpleAuthorizationInfo (); info.setStringPermissions (permsSet); return info } / * * obtain authentication information according to token * / @ Override protected AuthenticationInfo doGetAuthenticationInfo (AuthenticationToken token) throws AuthenticationException {System.out.println ("= get logged-in user, user information ="); String accessToken = (String) token.getPrincipal () / / query user information SysUserTokenEntity tokenEntity = shiroService.queryByToken (accessToken) according to accessToken; / / token failure if (tokenEntity = = null) {throw new IncorrectCredentialsException ("token failure, please log in again") } / / query user information SysUserEntity user = shiroService.queryUser (tokenEntity.getUserId ()); / / account lock if (user.getStatus (). Equals ("00")) {throw new LockedAccountException ("account is locked, please contact the administrator") } SimpleAuthenticationInfo info = new SimpleAuthenticationInfo (user, accessToken, getName () / / returns a unique Realm name); return info;}}

ShiroService is used to query user information and permission information from a database or cache.

Six: TokenGenerator

Public class TokenGenerator {public static String generateValue () {return generateValue (UUID.randomUUID (). ToString ());} private static final char [] hexCode = "0123456789abcdef" .toCharArray (); public static String toHexString (byte [] data) {if (data = = null) {return null;} StringBuilder r = new StringBuilder (data.length*2) For (byte b: data) {r.append (hexCode [(b > > 4) & 0xF]); r.append (hexCode [(b & 0xF)]);} return r.toString ();} public static String generateValue (String param) {try {MessageDigest algorithm = MessageDigest.getInstance ("MD5"); algorithm.reset () Algorithm.update (param.getBytes ()); byte [] messageDigest = algorithm.digest (); return toHexString (messageDigest);} catch (Exception e) {e.printStackTrace ();} return "";}}

Seven: Controller layer Demo

@ RestController@RequestMapping ("shiro") public class ShiroController {@ RequestMapping (value = "/ login", method = RequestMethod.GET) public String login () {return "login";} @ RequestMapping (value = "/ info", method = RequestMethod.GET) @ RequiresPermissions ("sys:config:info") public String info () {return "info";}}

Eight: login code

@ PostMapping ("/ sys/login") public Map login (@ RequestBody SysLoginForm form) throws IOException {boolean captcha = captchaService.validate (form.getUuid (), form.getCaptcha ()); if (! captcha) {return R.error ("incorrect CAPTCHA") } / / user information SysUserEntity user = sysUserService.queryByUserName (form.getUsername ()) / / account does not exist, password error if (user = = null | |! user.getPassword (). Equals (new Sha256Hash (form.getPassword (), user.getSalt ()). ToHex ()) {return R.error ("account or password is incorrect") } / / account lock if (Constant.CommonStatus.BANNED.getValue () .equals (user.getStatus () {return R.error ("account is locked, please contact the administrator") } / / generate token and save it to database R r = sysUserTokenService.createToken (user.getUserId ()); return r;}

Login verification is implemented independently. After successful verification, create a Token,Token and put it in the Redis cache. The front-end page should take Token when requesting the interface.

Nine: code call process

1. After the login is successful, create a Token, and all subsequent API calls need to pass Token

two。 The API is first filtered through shiroFilter to determine whether to enter OAuth3Filter for processing.

3.OAuth3Filter first executes the isAccessAllowed method. If OPTIONS requests a direct release, otherwise, executeLogin verification of Shiro will be performed.

When 4.executeLogin executes, it will call the doGetAuthenticationInfo method in OAuth3Realm to obtain the information of the currently logged-in user according to Token (the association between Token and user has been implemented in the login code of the eighth point)

After 5.executeLogin succeeds, it will look at the currently accessed API and whether it has permission annotation @ RequiresPermissions.

6. If there is a comment, it is said that permission verification is required. Shiro will use the doGetAuthorizationInfo method of OAuth3Realm to obtain the permissions of the current user for verification.

The above is all the contents of the article "how to use Spring Boot+Shiro to achieve rights management". Thank you for reading! Hope to share the content to help you, more related knowledge, welcome to follow the industry information channel!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report