For the data interception list, the SS official example is a simple configuration-based implementation, such as the following code:
1 <http>2 <Intercept-urlpattern= "/login.jsp*"Access= "is_authenticated_anonymously"/>3 <Intercept-urlpattern="/**"Access= "Role_user" />4 <Form-loginLogin-page= '/login.jsp '/>5 </http>
Such a hard code to join the configuration naturally does not meet the complex business requirements, the best implementation is to all the data using the database configuration, and then be free to add delete without affecting the program.
A list of data resources is typically applied when requesting resources, based on the resources accessed, to obtain the list of permissions required for the current resource, and then, based on the user's permissions, to determine whether the pass is allowed. So the list of data resources is equivalent to the data source at access time. All of our requests should be found in the list of data resources.
The custom data resource list should implement the Filterinvocationsecuritymetadatasource interface, and the SS default implementation is Defaultfilterinvocationsecuritymetadatasource. It has three implementations, namely Getallconfigattributes (), which returns the full set of configurations. GetAttributes (Object object), which returns the appropriate configuration based on the object currently being accessed. Supports (class<?> clazz), depending on the current object, determines whether the class operation is supported. The focus here is to get the configuration based on the current request resource, the GetAttributes (Object object) method. The method is to return a configuration of the object according to object, typically an object is a filterinvocation, which can be obtained to a URL resource, then it can be understood that the URL has any configuration (permissions). So you have to use the URL to store permissions, the map is best.
1 Public classMysecuritymetadatasourceImplementsFilterinvocationsecuritymetadatasource {2 3 @Autowired4 PrivateResourceservice Resourceservice;5 6 PrivateMap<string, collection<configattribute>>resource;7 8 Private voidLoadResource () {9Resource =NewLinkedhashmap<string, collection<configattribute>>();Tenmap<string, list<privilege>> Resource_privilege =Resourceservice.getresourceprivilege (); OneIterator<string> Iterator =Resource_privilege.keyset (). iterator (); A while(Iterator.hasnext ()) { -String URL =(String) Iterator.next (); -list<privilege> privileges =resource_privilege.get (URL); thecollection<configattribute> attributes =NewArraylist<configattribute>(); - for(Privilege privilege:privileges) { -Configattribute attribute =NewSecurityconfig (Privilege.getid (). toString ()); - Attributes.Add (attribute); + } - resource.put (URL, attributes); + } A } at - @Override - PublicCollection<configattribute>getallconfigattributes () { - return NULL; - } - in @Override - PublicCollection<configattribute> getattributes (Object object)throwsIllegalArgumentException { to //each time the currently requested resource is loaded from the database +SYSTEM.OUT.PRINTLN ("Request" + Object + "resource"); - LoadResource (); theHttpServletRequest request =((filterinvocation) object). Gethttprequest (); *Iterator<string> Iterator =Resource.keyset (). iterator (); $ while(Iterator.hasnext ()) {Panax NotoginsengString URL =(String) Iterator.next (); -Antpathrequestmatcher Antpathrequestmatcher =Newantpathrequestmatcher (URL); the if(antpathrequestmatcher.matches (Request)) { +SYSTEM.OUT.PRINTLN ("List of permission IDs for resource configuration:" +resource.get (URL)); A returnresource.get (URL); the } + } - return NULL; $ } $ - @Override - Public BooleanSupports (class<?>clazz) { the returnFilterinvocation.class. IsAssignableFrom (clazz); - }Wuyi the}
In 38 lines of code, a antpathrequestmatcher is used as a matching rule for the URL, and the antpathrequestmatcher matching rule is as follows:
1. * Match multiple characters at random, but not across directories
2. * * Any number of characters can be matched across the directory
3.? Match one character at any
Typically, Antpathrequestmatcher can meet our requirements, and if you can't meet complex business, you can use regexrequestmatcher, which supports regular expressions to match.
In the GetAttributes method, the LoadResource method is called, and the data table holding the data resource is requested in the LoadResource method. The table and permissions are associated with the following entity:
1 @Entity2 Public classMetaresourceImplementsSerializable {3 4 Private Static Final LongSerialversionuid = 1L;5 6 @Id7 @GeneratedValue8 PrivateLong ID;9 Ten @Column One PrivateString URL; A - @Column - PrivateString resourcename; the - @Column - PrivateLong sequence=0l; - +@ManyToMany (fetch=Fetchtype.eager) - @LazyCollection (Lazycollectionoption.false) +@JoinTable (name= "Resource_privilege", Ajoincolumns={@JoinColumn (name= "s_id", referencedcolumnname= "id")}, atinversejoincolumns={@JoinColumn (name= "p_id", referencedcolumnname= "id")}) - PrivateList<privilege>privileges; - - PublicLong getId () { - returnID; - } in - Public voidsetId (Long id) { to This. ID =ID; + } - the PublicString GetUrl () { * returnURL; $ }Panax Notoginseng - Public voidseturl (String url) { the This. url =URL; + } A the PublicList<privilege>getprivileges () { + returnprivileges; - } $ $ Public voidSetprivileges (list<privilege>privileges) { - This. Privileges =privileges; - } the - PublicString Getresourcename () {Wuyi returnresourcename; the } - Wu Public voidsetresourcename (String resourcename) { - This. resourcename =resourcename; About } $ - PublicLong getsequence () { - returnsequence; - } A + Public voidsetsequence (Long sequence) { the This. sequence =sequence; - } $}
View Code
In entity, a sequence attribute is added to record the sequential nature of the URL, which is equivalent to the sequential interception URL configured in HTTP. SS URL sequence is a special priority, that is, those who need to set permissions alone or have special permissions to put in front, because not to do so, it is possible to be intercepted in the previous URL, the underlying access is not , so we generally in the HTTP configuration, The login and other non-privileged pages will be placed at the top of the page to prevent access to the login page.
The service method for obtaining a permission resource is as follows, note the use of the linkedhashmap to ensure that the data we deposit is not disorderly :
1@SuppressWarnings ("Unchecked")2 PublicMap<string, list<privilege>>Getresourceprivilege () {3String queryString = "Select $ from Metaresource $ ORDER by $.sequence ASC";4Query query =em.createquery (queryString);5 //Query.unwrap (Sqlquery.class). Setresulttransformer (Transformers.alias_to_entity_map);6list<metaresource> resources =query.getresultlist ();7Map<string, list<privilege>> results =NewLinkedhashmap<string, list<privilege>>();8 for(Metaresource metaresource:resources) {9Results.put (Metaresource.geturl (), (list<privilege>) metaresource.getprivileges ());Ten } One returnresults; A}
Spring Security from database load access list of resources